Forget-Me-Not/helpers/datetime.nim

153 lines
6.6 KiB
Nim
Raw Normal View History

2025-05-15 08:01:35 -05:00
import std/[times, strutils]
proc weekdayFromString(dayStr: string): Weekday =
## Convert a string representation of a weekday to Weekday enum
case dayStr
of "Monday": return dMon
of "Tuesday": return dTue
of "Wednesday": return dWed
of "Thursday": return dThu
of "Friday": return dFri
of "Saturday": return dSat
of "Sunday": return dSun
proc monthFromString(monthStr: string): Month =
## Convert a string representation of a weekday to Weekday enum
case monthStr
of "January": return mJan
of "Febuary": return mFeb
of "March": return mMar
of "April": return mApr
of "May": return mMay
of "June": return mJun
of "July": return mJul
of "August": return mAug
of "September": return mSep
of "October": return mOct
of "November": return mNov
of "December": return mDec
proc nextWeekday*(targetWeekdayString: string): DateTime =
## Calculates the next occurrence of a specific weekday
var nextDate = now()
# We're not including current day, so we move to the next day
nextDate = nextDate + 1.days
#convert passed weekday string to nim Weekday.
let targetWeekday = weekdayFromString(targetWeekdayString)
# Find the next occurrence of the target weekday
while nextDate.weekday != targetWeekday:
nextDate = nextDate + 1.days
return nextDate
proc nthWeekdayInMonth*(year: int, month: Month, weekdayString: string, nth: range[1..3]): DateTime =
# Start from the first day of the month
#var currentDate = dateTime(year, month, 1, 0, 0, 0, 0)
var currentDate = dateTime(year, month, 1)
let weekday = weekdayFromString(weekdayString)
# Find the first occurrence of the specified weekday
while currentDate.weekday != weekday:
currentDate = currentDate + 1.days
# Move to the nth occurrence
currentDate = currentDate + days((nth - 1) * 7)
return currentDate
proc lastWeekdayInMonth(year: int, month: Month, weekdayString: string): DateTime =
# Create a DateTime for the last day of the given month
#var lastDay = dateTime(year, month, getDaysInMonth(month, year), 0, 0, 0, 0)
var lastDay = dateTime(year, month, getDaysInMonth(month, year))
let weekday = weekdayFromString(weekdayString)
# Work backwards until we find the last occurrence of the specified weekday
while lastDay.weekday != weekday:
lastDay = lastDay - 1.days
return lastDay
proc nextMonthlyOnWeekdayOfWeek*(weekdayString: string, ocurrence: string): DateTime =
var nextSendDate: DateTime
let nextMonthsDate = now() + 1.months
let weekNumStrings = @["1", "2", "3"]
if ocurrence in weekNumStrings:
nextSendDate = nthWeekdayInMonth(year(nextMonthsDate), month(nextMonthsDate), weekdayString, parseInt(ocurrence))
#when ocurrence == "last".
else:
nextSendDate = lastWeekdayInMonth(year(nextMonthsDate), month(nextMonthsDate), weekdayString)
#only use next month if that day has already occured this month, otherwise adjust it for this month instead.
if monthDay(nextSendDate - 1.months) > monthDay(now()):
if ocurrence in weekNumStrings:
nextSendDate = nthWeekdayInMonth(year(nextMonthsDate), month(now()), weekdayString, parseInt(ocurrence))
else:
nextSendDate = lastWeekdayInMonth(year(nextMonthsDate), month(now()), weekdayString)
return nextSendDate
proc nextYearlyOnWeekdayOfWeekOfMonth*(weekdayString, ocurrence, monthString: string): DateTime =
var nextSendDate, startingDate: DateTime
let nextYearsDate = now() + 1.years
#let startingDate = dateTime(year(nextYearsDate), monthFromString(monthString), 01, 0, 0, 0, 0)
startingDate = dateTime(year(nextYearsDate), monthFromString(monthString), 01)
let weekNumStrings = @["1", "2", "3"]
if ocurrence in weekNumStrings:
nextSendDate = nthWeekdayInMonth(year(startingDate), month(startingDate), weekdayString, parseInt(ocurrence))
#when ocurrence == "last".
else:
nextSendDate = lastWeekdayInMonth(year(startingDate), month(startingDate), weekdayString)
#only use next year if that month and day has already occured this year, otherwise adjust it for this year instead.
if nextSendDate - 1.years > now():
startingDate = dateTime(year(now()), monthFromString(monthString), 01)
let weekNumStrings = @["1", "2", "3"]
if ocurrence in weekNumStrings:
nextSendDate = nthWeekdayInMonth(year(startingDate), month(startingDate), weekdayString, parseInt(ocurrence))
#when ocurrence == "last".
else:
nextSendDate = lastWeekdayInMonth(year(startingDate), month(startingDate), weekdayString)
return nextSendDate
#[proc nextYearDate*(monthString: string, day: int): DateTime =
## Aalways returns a date in the next year,
## regardless of whether the target date has passed in the current year
#var nextSendDate = dateTime(year(now()) + 1, monthFromString(monthString), day, 0, 0, 0, 0)
#var nextSendDate = dateTime(year(now()) + 1, monthFromString(monthString), day)
#let nextSendDateString =
#echo nextSendDate
#return parse($nextSendDate, "yyyy-MM-dd")
var
let nextYear = year(now()) + 1
let dt = dateTime(nextYear, monthFromString(monthString), day, 00, 00, 00, 00)
#echo dt
let nextSendDateString = format(dt, "yyyy-MM-dd")
#echo nextSendDateString
#let nextSendDateString = $nextYear & "-" & formattedMonthString & "-" & $day
let nextSendDate = parse(nextSendDateString, "yyyy-MM-dd")
#echo nextSendDateString
return nextSendDate]#
proc nextYearlyDate*(monthString: string, targetDay: int): DateTime =
## Calculates a date for the next occurrence of a specific month and day
##
## Parameters:
## - baseDate: The starting date to calculate from
## - targetMonth: The month (Month enum) for the target date
## - targetDay: The day of month for the target date
##
## Returns the next occurrence of the specified month and day, which could be:
## - Later this year if the target date hasn't occurred yet
## - Next year if the target date has already passed this year
let baseDate = now()
let targetMonth = monthFromString(monthString)
# Get the current year
let currentYear = baseDate.year
# Create a DateTime for the target date in the current year
var nextSendDate = dateTime(currentYear, targetMonth, targetDay, 00, 00, 00, 00)
# If the target date has already passed this year, move to next year
if nextSendDate <= baseDate:
nextSendDate = dateTime(currentYear + 1, targetMonth, targetDay, 00, 00, 00, 00)
let nextSendDateString = format(nextSendDate, "yyyy-MM-dd")
#echo nextSendDateString
#let nextSendDateString = $nextYear & "-" & formattedMonthString & "-" & $day
nextSendDate = parse(nextSendDateString, "yyyy-MM-dd")
return nextSendDate