From 46e115b49a33de519fa3c864ba7562ce391a5071 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Fri, 28 Jun 2024 13:35:15 +0200 Subject: [PATCH] ADD datetime calculation Co-authored-by: LordBaryhobal --- src/datetime_calc.typ | 242 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 src/datetime_calc.typ diff --git a/src/datetime_calc.typ b/src/datetime_calc.typ new file mode 100644 index 0000000..60dcf22 --- /dev/null +++ b/src/datetime_calc.typ @@ -0,0 +1,242 @@ +#let is-leap-year(year) = { + if calc.rem(year, 4) != 0 { + return false + } + if calc.rem(year, 100) != 0 { + return true + } + return calc.rem(year, 400) == 0 +} + +#let get-month-days(month, year) = { + let leap = is-leap-year(year) + + if month == 2 { + return if leap {29} else {28} + } + + if month >= 8 { + month += 1 + } + return if calc.rem(month, 2) == 0 {30} else {31} +} + +#let add(dt, days) = { + assert(days >= 0, message: "days cannot be negative; use sub()") + + let day = dt.day() + let month = dt.month() + let year = dt.year() + let month-days = get-month-days(month, year) + let leap = is-leap-year(year) + + for _ in range(days) { + if day == month-days { + month += 1 + day = 1 + if month == 13 { + year += 1 + month = 1 + leap = is-leap-year(year) + } + month-days = get-month-days(month, year) + } else { + day += 1 + } + } + return datetime(day: day, month: month, year: year) +} + +#let sub(dt, days) = { + assert(days >= 0, message: "days cannot be negative; use add()") + + let day = dt.day() + let month = dt.month() + let year = dt.year() + let month-days = get-month-days(month, year) + let leap = is-leap-year(year) + + for _ in range(days) { + if day == 1 { + month -= 1 + if month == 0 { + year -= 1 + month = 12 + leap = is-leap-year(year) + } + month-days = get-month-days(month, year) + day = month-days + } else { + day -= 1 + } + } + return datetime(day: day, month: month, year: year) +} + +#let offset(dt, days) = { + if days < 0 { + return sub(dt, -days) + } + return add(dt, days) +} + +#let add-week-workingdays(dt, weeks) = { + let int_part = int(weeks) + let float_part = int( (weeks - int_part)*5 + 0.01 ) + let new_date = add(dt, int_part*7) + + let i = 0 + while i < float_part { + new_date = add(new_date, 1) + if new_date.weekday() == 6 { + new_date = add(new_date, 2) + } + if new_date.weekday() == 7 { + new_date = add(new_date, 1) + } + i += 1 + } + return new_date +} + +#let diff-days(a, b) = { + let days = 0 + let neg = b < a + if neg { + let c = a + a = b + b = c + } + while (a < b) { + days += 1 + a = add(a, 1) + } + return if neg {-days} else {days} +} +#let diff-weeks(start_date, finish_date) = { + calc.round( + diff-days( + start_date, + add(finish_date, 1) + )/7, + digits: 2 + ) +} +#let diff-weeks-workingday(start_date, finish_date) = { + let days = 0 + while (start_date <= finish_date) { + if start_date.weekday() != 6 and start_date.weekday() != 7 { + days += 1 + } + start_date = add(start_date, 1) + } + return days/5 +} +#let diff-months(start_date, finish_date) = { + calc.round( + diff-days( + start_date, + add(finish_date, 1) + )/30, + digits: 2 + ) +} + +#let count-weeks(a, b) = { + let weeks = 0 + let neg = b < a + if neg { + let c = a + a = b + b = c + } + while (a < b) { + weeks += 1 + a = add(a, 7) + } + return if neg {-weeks} else {weeks} +} +#let count-months(a, b) = { + let months = 0 + let neg = b < a + if neg { + let c = a + a = b + b = c + } + while (a < b) { + months += 1 + a = add(a, 30) + } + return if neg {-months} else {months} +} + +#let count-years(a, b) = { + let years = 0 + let neg = b < a + if neg { + let c = a + a = b + b = c + } + while (a < b) { + years += 1 + a = add(a, 365) + } + return if neg {-years} else {years} +} + +#let remaining_week_on_month(date) ={ + diff-weeks( + date, + datetime( + year: date.year(), + month: date.month(), + day: get-month-days(date.month(), date.year()) + ) + ) +} + +#let remaining_week_on_month-workingday(date) ={ + diff-weeks-workingday( + date, + datetime( + year: date.year(), + month: date.month(), + day: get-month-days(date.month(), date.year()) + ) + ) +} + +#let remaining_week_on_year(date) ={ + diff-weeks( + date, + datetime( + year: date.year(), + month: 12, + day: 31 + ) + ) +} + +#let workingday_ratio(date) = { + let weekday = date.weekday() -1 + if weekday == 6 { + weekday = 5 + } + if weekday == 7 { + weekday = 5 + } + return weekday/5 +} + + +#let equalDate(date1, date2) = { + let year = date1.year() == date2.year() + let month = date1.month() == date2.month() + let day = date1.day() == date2.day() + + return year and month and day +} + +