ADD datetime calculation
Co-authored-by: LordBaryhobal <lordbaryhobal@gmail.com>
This commit is contained in:
		
							
								
								
									
										242
									
								
								src/datetime_calc.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								src/datetime_calc.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user