Algorithms |
|
Date & Time |
|
Determine if a given year is a leap year
The function isLeapYear is part of the "time.s7i" library. It returns TRUE if the year is a leap year in the Gregorian calendar.
const func boolean: isLeapYear (in integer: year) is return (year rem 4 = 0 and year rem 100 <> 0) or year rem 400 = 0;
Compute the weekday
The function dayOfWeek is part of the "time.s7i" library. It delivers 1 for monday, 2 for tuesday, and so on up to 7 for sunday. This definition of weekday is according to the ISO 8601 week date.
const func integer: dayOfWeek (in time: aTime) is func result var integer: weekday is 0; local var integer: year is 0; var integer: month is 0; begin year := aTime.year; month := aTime.month; if month <= 2 then decr(year); month +:= 12; end if; weekday := succ(pred(year + year mdiv 4 - year mdiv 100 + year mdiv 400 + (31 * (month - 2)) mdiv 12 + aTime.day) mod 7); end func;
Compute the day of year
The function dayOfYear is part of the "time.s7i" library. It delivers 1 for the 1. of january.
const func integer: dayOfYear (in time: tim) is func result var integer: dayOfYear is 0; begin if isLeapYear(tim.year) then dayOfYear := [](0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335)[tim.month] + tim.day; else dayOfYear := [](0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334)[tim.month] + tim.day; end if; end func;
Compute the week number of a year
The function weekOfYear is part of the "time.s7i" library. According to ISO 8601: Week number 1 of every year contains the 4. of january. Since 1st to 3rd of january might be in the previous week there can be also a week number 0. This function computes week numbers from 0 to 53 for weeks belonging to the year of the given date.
const func integer: weekOfYear (in var integer: year, in integer: dayOfYear) is func result var integer: weekNumber is 0; local var integer: weekDayOfJan4 is 0; begin year := pred(year); weekDayOfJan4 := succ(pred(year + year mdiv 4 - year mdiv 100 + year mdiv 400 + 32) mod 7); weekNumber := (dayOfYear + weekDayOfJan4 - 5) mdiv 7 + 1; end func; const func integer: weekOfYear (in time: tim) is return weekOfYear(tim.year, dayOfYear(tim));
Compute the year of the ISO 8601 week date
The function weekDateYear is part of the "time.s7i" library. Compute the year of the ISO 8601 week date. At the beginning and the end of an Gregorian calendar year there might be days which belong to a week of the previous or next year. For example 2005-01-01 is 2004-W53-6 and 2007-12-31 is 2008-W01-1. The year returned by this function is in the range 'pred(tim.year)' to 'succ(tim.year)'.
const func integer: weekDateYear (in time: tim) is func result var integer: weekDateYear is 0; local var integer: weekNum is 0; begin weekNum := weekOfYear(tim.year, dayOfYear(tim)); if weekNum <= 0 then weekDateYear := pred(tim.year); elsif weekNum >= 53 and tim.day >= 29 and weekOfYear(succ(tim.year), 31 - tim.day) = 1 then weekDateYear := succ(tim.year); else weekDateYear := tim.year; end if; end func;
Compute the week of the ISO 8601 week date
The function weekDateWeek is part of the "time.s7i" library. Compute the week number of the ISO 8601 week date. At the beginning and the end of an Gregorian calendar year there might be days which belong to a week of the previous or next year. For example 2005-01-01 is 2004-W53-6 and 2007-12-31 is 2008-W01-1. The week number returned by this function is in the range 1 to 53.
const func integer: weekDateWeek (in time: tim) is func result var integer: weekNum is 0; begin weekNum := weekOfYear(tim.year, dayOfYear(tim)); if weekNum <= 0 then weekNum := weekOfYear(pred(tim.year), 366); elsif weekNum >= 53 and tim.day >= 29 and weekOfYear(succ(tim.year), 31 - tim.day) = 1 then weekNum := 1; end if; end func;
Calculate the number of days in a month
The function daysInMonth is part of the "time.s7i" library.
const func integer: daysInMonth (in integer: year, in integer: month) is func result var integer: leng is 0; local const set of integer: monthsOfLength31 is {1, 3, 5, 7, 8, 10, 12}; begin if month in monthsOfLength31 then leng := 31; else if month = 2 then if isLeapYear(year) then leng := 29; else leng := 28; end if; else leng := 30; end if; end if; end func;
Convert a time into a julian day number
The julian day number is the number of days that have elapsed since January 1, 4713 BC in the proleptic Julian calendar. The function julianDayNumber is part of the "time.s7i" library.
const func integer: julianDayNumber (in time: aTime) is func result var integer: julianDayNumber is 0; local var integer: year is 0; var integer: month is 0; begin year := aTime.year; month := aTime.month; if month <= 2 then decr(year); month +:= 12; end if; julianDayNumber := (1461 * (year + 4800)) mdiv 4 + (367 * (month - 2)) mdiv 12 - (3 * ((year + 4900) mdiv 100)) mdiv 4 + aTime.day - 32075; end func;
Convert a julian day number into a time
The julian day number is the number of days that have elapsed since January 1, 4713 BC in the proleptic Julian calendar. The function julianDayNumToTime is part of the "time.s7i" library.
const func time: julianDayNumToTime (in integer: julianDayNumber) is func result var time: aTime is time.value; local var integer: l is 0; var integer: n is 0; var integer: i is 0; var integer: j is 0; begin l := julianDayNumber + 68569; n := (4 * l) mdiv 146097; l := l - (146097 * n + 3) mdiv 4; i := (4000 * (l + 1)) mdiv 1461001; l := l - (1461 * i) mdiv 4 + 31; j := (80 * l) mdiv 2447; aTime.day := l - (2447 * j) mdiv 80; l := j mdiv 11; aTime.month := j + 2 - (12 * l); aTime.year := 100 * (n - 49) + i + l; end func;
Compute the easter date for a given year
const func time: easterDate (in integer: year) is func result var time: easterDate is time.value; local var integer: H1 is 0; var integer: H2 is 0; var integer: M is 0; var integer: N is 0; var integer: a is 0; var integer: b is 0; var integer: c is 0; var integer: d is 0; var integer: e is 0; var integer: f is 0; begin H1 := year mdiv 100; H2 := year mdiv 400; M := 15 + H1 - H2 - (8 * H1 + 13) mdiv 25; N := 4 + H1 - H2; # Gauss formula: a := year mod 19; b := year mod 4; c := year mod 7; d := (19 * a + M) mod 30; e := (2 * b + 4 * c + 6 * d + N) mod 7; f := 22 + d + e; if f = 57 then f := 50; end if; if d = 28 and e = 6 and a > 10 then f := 49; end if; easterDate.year := year; if f <= 31 then easterDate.month := 3; else easterDate.month := 4; f -:= 31; end if; easterDate.day := f; end func;
Compute seconds since the Unix Epoch
Return a time expressed in seconds since the Unix Epoch. The Unix Epoch (1970-01-01 00:00:00 UTC) corresponds to 0. The function timestamp1970 is part of the "time.s7i" library.
const func integer: timestamp1970 (in time: aTime) is func result var integer: seconds is 0; local var integer: yearBefore is 0; begin yearBefore := pred(aTime.year); seconds := (((yearBefore * 365 + yearBefore mdiv 4 - yearBefore mdiv 100 + yearBefore mdiv 400 - 719162 + pred(dayOfYear(aTime))) * 24 + aTime.hour) * 60 + aTime.minute) * 60 + aTime.second - aTime.timeZone * 60; end func;
Write a calendar
Write a calendar to standard output.
$ include "seed7_05.s7i"; include "time.s7i"; const func string: center (in string: stri, in integer: length) is return ("" lpad (length - length(stri)) div 2 <& stri) rpad length; const proc: printCalendar (in integer: year, in integer: cols) is func local var time: date is time.value; var integer: dayOfWeek is 0; const array string: monthNames is [] ("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); var array array string: monthTable is 12 times 9 times ""; var string: str is ""; var integer: month is 0; var integer: position is 0; var integer: row is 0; var integer: column is 0; var integer: line is 0; begin for month range 1 to 12 do monthTable[month][1] := " " & center(monthNames[month], 20); monthTable[month][2] := " Mo Tu We Th Fr Sa Su"; date := date(year, month, 1); dayOfWeek := dayOfWeek(date); for position range 1 to 43 do if position >= dayOfWeek and position - dayOfWeek < daysInMonth(date.year, date.month) then str := succ(position - dayOfWeek) lpad 3; else str := "" lpad 3; end if; monthTable[month][3 + pred(position) div 7] &:= str; end for; end for; writeln(center(str(year),cols * 24 + 4)); writeln; for row range 1 to succ(11 div cols) do for line range 1 to 9 do for column range 1 to cols do if pred(row) * cols + column <= 12 then write(" " & monthTable[pred(row) * cols + column][line]); end if; end for; writeln; end for; end for; end func; const proc: main is func begin printCalendar(1969, 3); end func;
|
|