Programming Language Cheat Sheets: Dates

Strings Mathematics Operators and Symbols General (Control Flow/Debugging) [TickCount] Dates Objects New Features Timelines Note: UFL: Universal Function Library, a set of around 100-300 standard functions for all programming languages. Languages do not have to implement anything exactly to the UFL specification, it is a guide. See lower down for further details. Note: Scroll to the bottom for date format links. UFL: Date Object [demonstrate Date object, by creating the local time now (see also 'DateNewLocalNow')] AutoHotkey: vDate := A_Now [e.g. vDate := 20060504030201][note: AutoHotkey uses 14-digit 'yyyyMMddHHmmss' integers, 'substrings' of length 4/6/8/10/12 are also valid] C++: C#: Crystal: Excel: NOW() [e.g. 38841 represents 2006-05-04 (38841 days since 1899-12-30)] Excel VBA: oDate = Now [type: Date] Go: Java: JavaScript: oDate = new Date() [type: Date] Kotlin: PHP: Python: oDate = datetime.datetime.now() [type: datetime] R: Ruby: Rust: Swift: UFL: DateFormatFriendly [show: weekday, Y/M/D/H/M/S, time zone] AutoHotkey: FormatTime(vDate, "ddd yyyy-MM-dd HH:mm:ss") [note: doesn't show time zone] C++: C#: Crystal: Excel: TEXT(A1,"ddd yyyy-mm-dd hh:mm:ss") [note: doesn't show time zone] Excel VBA: Format(oDate, "ddd yyyy-mm-dd hh:mm:ss") [note: doesn't show time zone] Go: Java: JavaScript: oDate.toString() [also: oDate.toLocaleString("en-GB", {timeZone:vTZ, dateStyle:"full", timeStyle:"full"})][e.g. vTZ = "UTC", vTZ = "Europe/London", vTZ = "America/New_York"] Kotlin: PHP: Python: oDate.strftime("%c %z") [also (without weekday): str(oDate)][also (without time zone): oDate.ctime()][note: local time zone: oDate.astimezone().strftime("%a %Y-%m-%d %H:%M:%S %z")] R: Ruby: Rust: Swift: UFL: DateNewUTCNow [create a date (UTC), the date/time now] AutoHotkey: vDate := A_NowUTC C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: oDate = new Date() Kotlin: PHP: Python: oDate = datetime.datetime.now().astimezone(datetime.timezone.utc) R: Ruby: Rust: Swift: UFL: DateNewUTC [create a date (UTC)] AutoHotkey: vDate := 20060504030201 C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: new Date(Date.UTC(2006, 5-1, 4, 3, 2, 1)) [WARNING: month is 0-based] Kotlin: PHP: Python: datetime.datetime(2006, 5, 4, 3, 2, 1, tzinfo=datetime.timezone.utc) R: Ruby: Rust: Swift: UFL: DateNewUTCFromStr [create a date (local time zone)][note: the functions can typically handle various date/time formats] AutoHotkey: vDate := "20060504030201" C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: new Date(Date.parse("2006-05-04 03:02:01 Z")) [note: 'Z' to treat strings as UTC] Kotlin: PHP: Python: datetime.datetime.strptime("20060504030201 +0000", "%Y%m%d%H%M%S %z") R: Ruby: Rust: Swift: UFL: DateNewLocalNow [create a date (local time zone), the date/time now] AutoHotkey: vDate := A_Now C++: C#: Crystal: Excel: NOW() [note: days since 1899-12-30][can use: TODAY() for the date only (with no time value)] Excel VBA: oDate = Now [also: oDate = Date + Time] Go: Java: JavaScript: oDate = new Date() Kotlin: PHP: Python: oDate = datetime.datetime.now() [also: to always print the time zone (offset-aware rather than offset-naive): datetime.datetime.now().astimezone()] R: Ruby: Rust: Swift: UFL: DateNewLocalMSec [get the current milliseconds (local time zone)] AutoHotkey: vMSec := A_MSec C++: C#: Crystal: Excel: RIGHT(TEXT(NOW(),"s.000"),3) Excel VBA: vMSec = (Timer * 1000) Mod 1000 Go: Java: JavaScript: vMSec = new Date().getMilliseconds() Kotlin: PHP: Python: vMSec = datetime.datetime.now().microsecond//1000 R: Ruby: Rust: Swift: UFL: DateNewLocal [create a date (local time zone)] AutoHotkey: vDate := 20060504030201 C++: C#: Crystal: Excel: DATE(2006,5,4)+TIME(3,2,1) Excel VBA: oDate = DateSerial(2006, 5, 4) + TimeSerial(3, 2, 1) Go: Java: JavaScript: new Date(2006, 5-1, 4, 3, 2, 1) [WARNING: month is 0-based] Kotlin: PHP: Python: datetime.datetime(2006, 5, 4, 3, 2, 1) [also: to always print the time zone: datetime.datetime(2006, 5, 4, 3, 2, 1).astimezone()] R: Ruby: Rust: Swift: UFL: DateNewLocalWithFold [create a date (local time zone) (local time zones often have an ambiguous hour when DST ends)] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: new Date(Date.parse("1999-10-31 01:30:00 GMT+0000")) [note: use 'GMT+0000' or 'GMT+0100', for the earlier/later time] Kotlin: PHP: Python: datetime.datetime(1999, 10, 31, 1, 30, 0, fold=0) [note: set fold to 0 or 1, for the earlier/later time][e.g. the UK, 1999-10-31, had 1am BST followed by 1am GMT] R: Ruby: Rust: Swift: UFL: DateNewLocalFromStr [create a date (local time zone)][note: the functions can typically handle various date/time formats] AutoHotkey: vDate := "20060504030201" C++: C#: Crystal: Excel: DATEVALUE("2006-05-04 03:02:01")+TIMEVALUE("2006-05-04 03:02:01") Excel VBA: oDate = CDate("2006-05-04 03:02:01") [also: DateValue("2006-05-04 03:02:01") + TimeValue("2006-05-04 03:02:01")] Go: Java: JavaScript: new Date(Date.parse("2006-05-04 03:02:01")) Kotlin: PHP: Python: datetime.datetime.strptime("20060504030201", "%Y%m%d%H%M%S") [also: to always print the time zone: datetime.datetime.strptime("20060504030201", "%Y%m%d%H%M%S").astimezone()] R: Ruby: Rust: Swift: UFL: DateFormat [create a date string using substrings, show: weekday, Y/M/D/H/M/S, time zone] AutoHotkey: FormatTime(vDate, "ddd yyyy-MM-dd HH:mm:ss") [note: doesn't show time zone][note: uses the Winapi's GetDateFormat/GetTimeFormat] C++: C#: Crystal: Excel: TEXT(A1,"ddd yyyy-mm-dd hh:mm:ss") [note: doesn't show time zone][WARNING: 'smart' behaviour is needed to determine whether 'm' means *month* or *minute* (e.g. by observing whether 'h'/'s' is near, 'm' by itself is month)][WARNING: TEXT with 'ddd'/'dddd' gives incorrect values for Jan 1900 and Feb 1900 (e.g. 1900-01-01 was actually a Monday)] Excel VBA: Format(oDate, "ddd yyyy-mm-dd hh:mm:ss") [note: doesn't show time zone][WARNING: 'smart' behaviour is needed to determine whether 'm' means *month* or *minute* (e.g. by observing whether 'h' precedes 'm', 'm' by itself is month)][WARNING: Excel VBA also has 'n' for minutes, but Excel sheet functions lack this][note: 'ddd'/'dddd' in Format and WorksheetFunction.Text give correct values for Jan 1900 and Feb 1900] Go: Java: JavaScript: ___ [note: toLocaleString() has various options e.g. oDate.toLocaleString("en-CA-u-hc-h23", {weekday:"short", year:"numeric", month:"2-digit", day:"2-digit", hour:"2-digit", minute:"2-digit", second:"2-digit", timeZoneName:"longOffset"})] Kotlin: PHP: Python: oDate.strftime("%a %Y-%m-%d %H:%M:%S %z") R: Ruby: Rust: Swift: UFL: DateFormatISOUTC [UTC time as ISO string, no time zone: '####-##-##T##:##:##.###Z' e.g. '2006-05-04T03:02:01.000Z'] AutoHotkey: FormatTime(vDate, "yyyy-MM-ddTHH:mm:ss.000Z") [note: assumes 0 milliseconds] C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: oDate.toISOString() [note: the return value is in the UTC time zone (the local time zone is ignored)] Kotlin: PHP: Python: oDate.astimezone(datetime.timezone.utc).strftime("%FT%T.%f")[:-3]+"Z" [also: oDate.astimezone(datetime.timezone.utc).isoformat(timespec="milliseconds")[:23] + "Z"][note: F%/T% aren't listed on the Python documentation] R: Ruby: Rust: Swift: UFL: DateFormatISOLocal [local time as ISO string, no time zone: '####-##-##T##:##:##.###Z' e.g. '2006-05-04T03:02:01.000Z'] AutoHotkey: FormatTime(vDate, "yyyy-MM-ddTHH:mm:ss.000Z") [WARNING: prints 0 milliseconds] C++: C#: Crystal: Excel: TEXT(A1,"yyyy-mm-ddThh:mm:ss.000Z") [note: *does* handle milliseconds (the Excel sheet function does, Excel VBA doesn't)] Excel VBA: Format(oDate, "yyyy-mm-ddThh:mm:ss.000Z") [WARNING: prints 0 milliseconds] Go: Java: JavaScript: vDate = new Date(oDate.valueOf()-oDate.getTimezoneOffset()*60000).toISOString() [note: valueOf/getTime are interchangeable] Kotlin: PHP: Python: oDate.astimezone().strftime("%FT%T.%f")[:-3]+"Z" [also: oDate.astimezone().isoformat(timespec="milliseconds")[:23] + "Z"][note: F%/T% aren't listed on the Python documentation] R: Ruby: Rust: Swift: UFL: DateFormat14 [14-digit string (yyyyMMddHHmmss)] AutoHotkey: FormatTime(vDate, "yyyyMMddHHmmss") C++: C#: Crystal: Excel: TEXT(A1,"yyyymmddhhmmss") Excel VBA: Format(oDate, "yyyymmddhhmmss") Go: Java: JavaScript: oDate.toISOString().replace(/\D+/g, "").slice(0, 14) [note: returns UTC time][also (fairly similar): (using af/lt/sv/en-CA-u-hc-h23 locales): oDate.toLocaleString("af", {timeZone:"UTC"})][note: '-u-hc-h23' means use 24-hour time][note: using locales is best avoided as formats sometimes change] Kotlin: PHP: Python: oDate.strftime("%Y%m%d%H%M%S") R: Ruby: Rust: Swift: UFL: DateSplit [6-item array e.g. string (yyyy,MM,dd,HH,mm,ss) or numeric (yyyy,M,d,H,m,s)] AutoHotkey: StrSplit(FormatTime(vDate, "yyyy|MM|dd|HH|mm|ss"), "|") [note: will preserve any leading zeros] C++: C#: Crystal: Excel: ___ [note: can use: TEXT(A1,"yyyy|mm|dd|hh|mm|ss")] Excel VBA: Split(Format(oDate, "yyyy|mm|dd|hh|mm|ss"), "|") Go: Java: JavaScript: oDate.toISOString().split(/\D+/g, 6) [note: returns UTC time] Kotlin: PHP: Python: str.split(oDate.strftime("%Y|%m|%d|%H|%M|%S"), "|") R: Ruby: Rust: Swift: UFL: DateGetTZOffsetMinLocal [e.g. 60 or -60 (for time zone '+01:00') (at a particular moment in time, what was the offset from UTC (including any DST) for the local time zone] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: vOffsetMin = oDate.getTimezoneOffset() [e.g. returns 60 for '+01:00'][e.g. new Date(2006, 7-1, 1).getTimezoneOffset()] Kotlin: PHP: Python: oDate.astimezone().utcoffset().total_seconds()//60 [e.g. returns 60 for '+01:00'][also (to get both offsets): time.timezone//60 and time.altzone//60 (e.g. they return 0 and -60 respectively for Europe/London ('+01:00'))] R: Ruby: Rust: Swift: UFL: DateGetTZOffsetMin [e.g. 60 or -60 (for time zone '+01:00') (at a particular moment in time, what was the offset from UTC (including any DST) for a specific time zone] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: vOffsetMin = (Date.parse(oDate.toLocaleString("en",{timeZone:"UTC"})+" Z")-Date.parse(oDate.toLocaleString("en",{timeZone:vTZ})+" Z"))/60000 [note: 'Z' to treat strings as UTC][e.g. returns -60 for '+01:00'][e.g. vTZ = "America/New_York"] Kotlin: PHP: Python: oDate.astimezone(oTZ).utcoffset().total_seconds()//60 [e.g. returns 60 for '+01:00'] R: Ruby: Rust: Swift: UFL: DateGetTZOffsetStrLocal [e.g. '+01:00'/'+0100' (the number varies depending on whether DST is in force)] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: vOffset = oDate.toLocaleString("en", {day:"2-digit", timeZoneName:"longOffset"}).slice(7) || "+00:00" Kotlin: PHP: Python: oDate.astimezone().strftime("%z") [e.g. '+0100'][also: '%:z' (e.g. '+01:00')] R: Ruby: Rust: Swift: UFL: DateGetTZOffsetStr [e.g. '+01:00'/'+0100' (the number varies depending on whether DST is in force)] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: vOffset = oDate.toLocaleString("en", {timeZone:vTZ, day:"2-digit", timeZoneName:"longOffset"}).slice(7) || "+00:00" [e.g. vTZ = "Europe/London"] Kotlin: PHP: Python: oDate.strftime("%z") [e.g. '+0100'][also: '%:z' (e.g. '+01:00')] R: Ruby: Rust: Swift: UFL: DateGetTZLocationLocal [e.g. 'Europe/London' / 'America/New_York'] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: vTZ = Intl.DateTimeFormat().resolvedOptions().timeZone [e.g. 'Europe/London'] Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateGetTZNameLocal [e.g. 'Greenwich Mean Time'/'British Summer Time'/'Eastern Standard Time'][note: the name can vary depending on DST] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: vTZName = oDate.toLocaleString("en", {day:"2-digit", timeZoneName:"long"}).slice(4) Kotlin: PHP: Python: time.tzname [note: returns both as a tuple, e.g. '('GMT Standard Time', 'GMT Daylight Time')'][can use (to return a time zone, although '%Z' should be avoided as it's OS-specific): oDate.astimezone().strftime("%Z")] R: Ruby: Rust: Swift: UFL: DateGetTZName [e.g. 'Greenwich Mean Time'/'British Summer Time'/'Eastern Standard Time'][note: the name can vary depending on DST] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: vTZName = oDate.toLocaleString("en", {timeZone:vTZ, day:"2-digit", timeZoneName:"long"}).slice(4) [e.g. vTZ = "Europe/London"] Kotlin: PHP: Python: ___ [WARNING: 'If neither system data nor tzdata are available, all calls to ZoneInfo will raise ZoneInfoNotFoundError.'] R: Ruby: Rust: Swift: UFL: DateAdd [e.g. add days/hours/minutes/seconds/milliseconds] AutoHotkey: DateAdd(vDate, vAmount, vUnit) [note: doesn't handle milliseconds] C++: C#: Crystal: Excel: =A1+vDays [e.g. 0.5 = 12 hours] Excel VBA: DateAdd("s", vSec, oDate) Go: Java: JavaScript: oDate = new Date(oDate.valueOf() + vMSec) [note: valueOf/getTime are interchangeable] Kotlin: PHP: Python: oDate + datetime.timedelta(seconds=vSec) R: Ruby: Rust: Swift: UFL: DateAddMonths [prefer the algorithm used by Excel's EDATE function] AutoHotkey: ___ C++: C#: Crystal: Excel: EDATE(A1,vMonths) Excel VBA: DateAdd("m", vMonths, oDate) Go: Java: JavaScript: oDate.setUTCMonth(oDate.getUTCMonth() + vMonths) [WARNING: adding 1 month, can increase the month by 2: 'if the current value is 31st January 2016, calling setMonth with a value of 1 will return 2nd March 2016'] Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateAddYears [prefer the algorithm used by Excel's EDATE function] AutoHotkey: ___ C++: C#: Crystal: Excel: EDATE(A1,vYears*12) Excel VBA: DateAdd("yyyy", vYears, oDate) Go: Java: JavaScript: oDate.setUTCMonth(oDate.getUTCMonth() + vYears*12) [WARNING: adding 1 month, can increase the month by 2: 'if the current value is 31st January 2016, calling setMonth with a value of 1 will return 2nd March 2016'] Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateAddWorkdays [add working days to current date, specify a list of dates to exclude] AutoHotkey: ___ C++: C#: Crystal: Excel: A1-INT(A1)+WORKDAY(A1,vDays) [also: MOD(A1,1)+WORKDAY(A1,vDays)][note: or for the date only (with no time value): WORKDAY(A1,vDays)] Excel VBA: TimeValue(oDate) + WorksheetFunction.WorkDay(oDate, vDays) [note: or for the date only (with no time value): CDate(WorksheetFunction.WorkDay(oDate, vDays))] Go: Java: JavaScript: ___ Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateDiff [e.g. difference in days/hours/minutes/seconds/milliseconds] AutoHotkey: DateDiff(vDate1, vDate2, vUnit) [note: doesn't handle milliseconds] C++: C#: Crystal: Excel: =A1-B1 [note: difference in days, e.g. 0.5 is a difference of 12 hours][WARNING: gives incorrect values for Jan 1900 and Feb 1900 (e.g. 1900-03-01 minus 1900-02-28 is actually 1 day)] Excel VBA: DateDiff("s", oDate1, oDate2) [WARNING: returns oDate2-oDate1 (oDate1-oDate2 would be more intuitive)][note: DateDiff gives correct values for Jan 1900 and Feb 1900] Go: Java: JavaScript: Math.floor((oDate1.valueOf()-oDate2.valueOf())/vMSec) [note: valueOf/getTime are interchangeable] Kotlin: PHP: Python: (oDate2-oDate1).total_seconds() R: Ruby: Rust: Swift: UFL: DateDiffMonths [count complete months (e.g. tiebreaks: Month1>Month2 but Day1<Day2, return vMonth1-vMonth2-1]) AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: ___ Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateDiffYears [count complete years (e.g. tiebreaks: Year1>Year2 but Month1<Month2, return vYear1-vYear2-1)] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: ___ Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateIsValid [validate numbers/string][note: the functions can typically handle various date/time formats] AutoHotkey: IsTime(vDate) C++: C#: Crystal: Excel: ISNUMBER(DATEVALUE("2006-05-04 03:02:01")+TIMEVALUE("2006-05-04 03:02:01")) [WARNING: this is not 100% reliable, try changing one or more parts to '99' to see which pass/fail] Excel VBA: IsDate("2006-05-04 03:02:01") Go: Java: JavaScript: vDateIsValid = !isNaN(Date.parse("2006-05-04 03:02:01")) Kotlin: PHP: Python: ___ [note: datetime.datetime() throws if given invalid input] R: Ruby: Rust: Swift: UFL: DateEaster AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: ___ Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateWeekdayNearest [(or DateWorkdayNearest) nearest working day to a specific date (if Sat, go back 1, if Sun, go forward 1) (i.e. choose the nearest M/T/W/T/F, a more general function lets you pick which weekdays)] AutoHotkey: ___ C++: C#: Crystal: Excel: A1+MID("2111110",WEEKDAY(A1),1)-1 [note: WEEKDAY: 1-7, Sun = 1] Excel VBA: oDate = oDate + Mid("2111110", Weekday(oDate), 1) - 1 [note: Weekday: 1-7, Sun = 1] Go: Java: JavaScript: oDate = new Date(Date.UTC(oDate.getFullYear(), oDate.getMonth(), oDate.getDate() + [1,0,0,0,0,0,-1][oDate.getDay()])) Kotlin: PHP: Python: oDate = oDate + datetime.timedelta(days=[0,0,0,0,0,-1,1][oDate.weekday()]) [WARNING: if the date is not UTC, this could skip by 2 days, e.g. on the day UTC starts, e.g. the UK, 1999-03-28 00:59:00 + 1 day] R: Ruby: Rust: Swift: UFL: DateWeekdayNthInRange [nth weekday in range (e.g. 1st/2nd/3rd/4th/last Sunday of the month)] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: ___ Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateGetYear AutoHotkey: FormatTime(vDate, "yyyy") C++: C#: Crystal: Excel: YEAR(A1) Excel VBA: Year(oDate) Go: Java: JavaScript: oDate.getUTCFullYear() [also: oDate.getFullYear()] Kotlin: PHP: Python: oDate.year R: Ruby: Rust: Swift: UFL: DateGetMonth AutoHotkey: FormatTime(vDate, "M") [note: 'MM' for leading zeros] C++: C#: Crystal: Excel: MONTH(A1) Excel VBA: Month(oDate) Go: Java: JavaScript: oDate.getUTCMonth()+1 [also: oDate.getMonth()+1][WARNING: getUTCMonth/getMonth are 0-based] Kotlin: PHP: Python: oDate.month R: Ruby: Rust: Swift: UFL: DateGetDay AutoHotkey: FormatTime(vDate, "d") [note: 'dd' for leading zeros] C++: C#: Crystal: Excel: DAY(A1) Excel VBA: Day(oDate) Go: Java: JavaScript: oDate.getUTCDate() [also: oDate.getDate()][WARNING: 'Date' not 'Day'] Kotlin: PHP: Python: oDate.day R: Ruby: Rust: Swift: UFL: DateGetHours AutoHotkey: FormatTime(vDate, "H") [note: 'HH' for leading zeros] C++: C#: Crystal: Excel: HOUR(A1) Excel VBA: Hour(oDate) Go: Java: JavaScript: oDate.getUTCHours() [also: oDate.getHours()] Kotlin: PHP: Python: oDate.hour R: Ruby: Rust: Swift: UFL: DateGetMinutes AutoHotkey: FormatTime(vDate, "m") [note: 'mm' for leading zeros] C++: C#: Crystal: Excel: MINUTE(A1) Excel VBA: Minute(oDate) Go: Java: JavaScript: oDate.getUTCMinutes() [also: oDate.getMinutes()] Kotlin: PHP: Python: oDate.minute R: Ruby: Rust: Swift: UFL: DateGetSeconds AutoHotkey: FormatTime(vDate, "s") [note: 'ss' for leading zeros] C++: C#: Crystal: Excel: SECOND(A1) Excel VBA: Second(oDate) Go: Java: JavaScript: oDate.getUTCSeconds() [also: oDate.getSeconds()] Kotlin: PHP: Python: oDate.second R: Ruby: Rust: Swift: UFL: DateGetMilliseconds AutoHotkey: ___ C++: C#: Crystal: Excel: RIGHT(TEXT(A1,"s.000"),3) [also: MOD(ROUND((A1-INT(A1))*86400000,0),1000)] Excel VBA: Round((oDate - Int(oDate)) * 86400000) Mod 1000 Go: Java: JavaScript: oDate.getUTCMilliseconds() [also: oDate.getMilliseconds()] Kotlin: PHP: Python: oDate.microsecond//1000 R: Ruby: Rust: Swift: UFL: DateGetWDay [(or DateGetWeekday) typically 0-6 or 1-7] AutoHotkey: FormatTime(vDate, "WDay") [note: 1-7, Sun = 1] C++: C#: Crystal: Excel: WEEKDAY(A1) [note: 1-7, Sun = 1 (but can use 2nd param to use other weekday systems)][WARNING: WEEKDAY gives incorrect values for Jan 1900 and Feb 1900 (e.g. 1900-01-01 was actually a Monday)] Excel VBA: Weekday(oDate) [note: 1-7, Sun = 1 (but can use 2nd param to use other weekday systems)][note: Weekday and WorksheetFunction.Weekday give correct values for Jan 1900 and Feb 1900] Go: Java: JavaScript: oDate.getUTCDay() [also: oDate.getDay()][WARNING: 'Day' not 'WDay'/'Weekday'][note: 0-6, Sun = 0] Kotlin: PHP: Python: oDate.isoweekday() [note: 1-7, Mon = 1][also: oDate.weekday() (0-6, Mon = 0)] R: Ruby: Rust: Swift: UFL: DateGetWeek [get week number (week containing January 1st is numbered week 1, week starts on Monday)] AutoHotkey: ___ C++: C#: Crystal: Excel: WEEKNUM(A1,2) Excel VBA: Format(oDate, "ww", vbMonday) Go: Java: JavaScript: ___ Kotlin: PHP: Python: int(oDate.strftime("%W")) + (1 if datetime.date(oDate.year,1,1).weekday() else 0) R: Ruby: Rust: Swift: UFL: DateGetISOWeek [get ISO week number (week containing the first Thursday of the year is numbered week 1, week starts on Monday)] AutoHotkey: FormatTime(vDate, "YWeek") [note: number of the form 'yyyyww'] C++: C#: Crystal: Excel: ISOWEEKNUM(A1) [also: WEEKNUM(A1,21)][note: ISOWEEKNUM added in Excel 2013, WEEKNUM '21' option added in Excel 2010][WARNING: returns the week number 1-53, but not the year, which doesn't always match YEAR(oDate)] Excel VBA: WorksheetFunction.IsoWeekNum(oDate) [WARNING: returns the week number 1-53, but not the year, which doesn't always match Year(oDate)][WARNING: Format/DatePart with 'ww'/vbMonday/vbFirstFourDays sometimes return the wrong week: 'the last Monday in some calendar years is returned as week 53 when it should be week 1'] Go: Java: JavaScript: ___ Kotlin: PHP: Python: oDate.strftime("%G%V") [also: oDate.isocalendar(): contains year/week(/weekday) values] R: Ruby: Rust: Swift: UFL: DateGetMonthName [e.g. Jan/Feb/Mar/Apr/May/Jun/Jul/Aug/Sep/Oct/Nov/Dec] AutoHotkey: FormatTime(vDate, "MMMM") [note: 'MMM' for short version] C++: C#: Crystal: Excel: TEXT(A1,"mmmm") [note: 'mmm' for short version] Excel VBA: Format(oDate, "mmmm") [note: 'mmm' for short version][also: MonthName(DatePart("m", oDate))] Go: Java: JavaScript: oDate.toLocaleString("en", {month:"long"}) [note: 'short' for short version] Kotlin: PHP: Python: oDate.strftime("%B") [note: '%b' for short version] R: Ruby: Rust: Swift: UFL: DateGetWDayName [(or DateGetWeekdayName) e.g. Mon/Tue/Wed/Thu/Fri/Sat/Sun] AutoHotkey: FormatTime(vDate, "dddd") [note: 'ddd' for short version] C++: C#: Crystal: Excel: TEXT(A1,"dddd") [note: 'ddd' for short version] Excel VBA: Format(oDate, "dddd") [note: 'ddd' for short version][can use: WeekdayName(Weekday(oDate), , vbSunday)][WARNING: WeekdayName default: 1-7, Mon = 1 (differs from Weekday function), can use: vbSunday: 1-7, Sun = 1 (matches Weekday function)] Go: Java: JavaScript: oDate.toLocaleString("en", {weekday:"long"}) [note: 'short' for short version] Kotlin: PHP: Python: oDate.strftime("%A") [note: '%a' for short version] R: Ruby: Rust: Swift: UFL: DateGetHour12 [(or DateGetHourAmPm) i.e. 1-12] AutoHotkey: FormatTime(vDate, "h") [note: 'hh' for leading zeros] C++: C#: Crystal: Excel: MOD(HOUR(A1)+11,12)+1 Excel VBA: ((Hour(oDate) + 11) Mod 12) + 1 Go: Java: JavaScript: oDate.getUTCHours()%12||12 [also: oDate.getHours()%12||12] Kotlin: PHP: Python: oDate.strftime("%I") R: Ruby: Rust: Swift: UFL: DateGetAmPm [e.g. AM/PM] AutoHotkey: FormatTime(vDate, "tt") [e.g. AM/PM][note: 't' for short version (e.g. A/P)] C++: C#: Crystal: Excel: TEXT(A1,"AM/PM") Excel VBA: Format(oDate, "AM/PM") Go: Java: JavaScript: oDate.getUTCHours()<12?"AM":"PM" [also: oDate.getHours()<12?"AM":"PM"] Kotlin: PHP: Python: oDate.strftime("%p") [WARNING: confusingly: %p returns upper case, %P returns lower case] R: Ruby: Rust: Swift: UFL: DateGetDaySuffix [i.e. st/nd/rd/th (e.g. 1st/2nd/3rd/4th) (ordinal suffixes)][the algorithm aims to be short, readable, and handle all positive integers and 0 (pass abs(vNum) to handle all integers)] AutoHotkey: vSfx := Abs(Mod(vNum,100)-12)<=1?"th":["st","nd","rd","th"][Min(Mod(vNum+9,10),3)+1] C++: C#: Crystal: Excel: IF(ABS(MOD(A1,100)-12)<=1,"th",MID("stndrdth",MIN(MOD(A1+9,10),3)*2+1,2)) Excel VBA: vSfx = IIf(Abs((vNum Mod 100) - 12) <= 1, "th", Mid("stndrdth", WorksheetFunction.Min(((vNum + 9) Mod 10), 3) * 2 + 1, 2)) Go: Java: JavaScript: vSfx = Math.abs(vNum%100-12)<=1?"th":["st","nd","rd"][vNum%10-1]||"th" Kotlin: PHP: Python: vSfx = "th" if (abs(vNum%100-12)<=1) else ["st","nd","rd","th"][min((vNum+9)%10,3)] R: Ruby: Rust: Swift: UFL: DateGetYDay [i.e. 1-366] AutoHotkey: FormatTime(vDate, "YDay") [note: 'YDay0' for leading zeros] C++: C#: Crystal: Excel: A1-DATE(YEAR(A1),1,0) Excel VBA: DatePart("y", oDate) [also: Format(oDate, "y")][WARNING: in Excel sheet functions, 'y' returns the 2-digit year] Go: Java: JavaScript: vYDay = (Date.UTC(oDate.getFullYear(), oDate.getMonth(), oDate.getDate()) - Date.UTC(oDate.getFullYear(), 0, 0)) / 86400000 Kotlin: PHP: Python: oDate.timetuple().tm_yday [also: oDate.strftime("%j")] R: Ruby: Rust: Swift: UFL: (DateGetEra) [(or DateGetBcAd) e.g. BC/AD] AutoHotkey: FormatTime(vDate, "gg") [e.g. 'A.D.'] C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: oDate.toLocaleString("en", {year:"2-digit", era:"short"}).slice(3) [e.g. 'AD'] Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateGetMonthEnd [modify date, set day to last day of month] AutoHotkey: ___ [can use: DateAdd and SubStr: get first day of current month, add 31 days to fall inside new month, get the day of the new month, subtract that many days] C++: C#: Crystal: Excel: EOMONTH(A1,0) Excel VBA: CDate(WorksheetFunction.EoMonth(oDate, 0)) [also: DateSerial(Year(oDate), Month(oDate) + 1, 0) (note: '0th' day of month, goes back 1 day)] Go: Java: JavaScript: new Date(oDate.getFullYear(), oDate.getMonth()+1, 0) Kotlin: PHP: Python: calendar.monthrange(oDate.year, oDate.month)[1] R: Ruby: Rust: Swift: UFL: DateGetQuarter [i.e. Jan/Feb/Mar to 1, Apr/May/Jun to 2, Jul/Aug/Sep to 3, Oct/Nov/Dec to 4] AutoHotkey: (FormatTime(vDate, "M")+2)//3 C++: C#: Crystal: Excel: INT((MONTH(A1)+2)/3) Excel VBA: DatePart("q", oDate) [also: Format(oDate, "q")][WARNING: Excel sheet functions lack the 'q' option] Go: Java: JavaScript: Math.floor(oDate.getUTCMonth()/3+1) [also: Math.floor(oDate.getMonth()/3+1)][WARNING: getUTCMonth/getMonth are 0-based] Kotlin: PHP: Python: (oDate.month+2)//3 R: Ruby: Rust: Swift: UFL: DateGetWeekdayCount [count weekdays in date range, specify a list of dates to exclude] AutoHotkey: ___ C++: C#: Crystal: Excel: NETWORKDAYS(A1,B1) Excel VBA: WorksheetFunction.NetworkDays(oDate1, oDate2) Go: Java: JavaScript: ___ Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateIsLeapYear [for a date, is the year a leap year] AutoHotkey: vIsLeapYear := !Mod(vYear, 4) && (Mod(vYear, 100) || !Mod(vYear, 400)) [beforehand: vYear := FormatTime(vDate, "yyyy")] C++: C#: Crystal: Excel: IF(OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)<>0)),True,False) [note: where A1 contains a year][note: date to year: YEAR(A1)][note: based on code from learn.microsoft.com] Excel VBA: vIsLeapYear = (Month(DateSerial(vYear, 2, 29)) = 2) [beforehand: vYear = Year(oDate)] Go: Java: JavaScript: vIsLeapYear = (new Date(vYear, 2-1, 29).getDate() == 29) [beforehand: vYear = oDate.getFullYear()] Kotlin: PHP: Python: vIsLeapYear = calendar.isleap(vYear) [beforehand: vYear = oDate.year] R: Ruby: Rust: Swift: UFL: DateIsDSTLocal [for a given time, was DST in force at that time, using the local time zone] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: vIsDST = (oDate.getTimezoneOffset() < Math.max(new Date(oDate.getFullYear(), 6, 1).getTimezoneOffset(), new Date(oDate.getFullYear(), 0, 1).getTimezoneOffset())) [WARNING: it happens to work for almost every time zone, but is not guaranteed to work] Kotlin: PHP: Python: vIsDST = (oDate.astimezone().utcoffset().total_seconds() != -time.timezone) [note: if offset is not the standard (non-DST) offset, it must be DST offset] R: Ruby: Rust: Swift: UFL: DateIsDST [for a given time, was DST in force at that time, using a specific time zone] AutoHotkey: ___ C++: C#: Crystal: Excel: ___ Excel VBA: ___ Go: Java: JavaScript: ___ [note: toLocaleString() and Date.parse() can be used on a sample of dates (e.g. 1 date per month), to determine the DST/non-DST UTC offsets for a time zone, and that can be compared with the current UTC offset (see the 'DateGetTZOffsetMin' example)] Kotlin: PHP: Python: ___ R: Ruby: Rust: Swift: UFL: DateSetPart [(or DateSetValue) e.g. set Y/M/D/H/M/S] AutoHotkey: ___ [e.g. StrPut(), to overwrite part of a date string] C++: C#: Crystal: Excel: ___ [can use: DATE/TIME and YEAR/MONTH/DAY/HOUR/MINUTE/SECOND][also: INT(A1) gets the date value, A1-INT(A1) or MOD(A1,1) gets the time value] Excel VBA: ___ [can use: DateSerial/TimeSerial and Year/Month/Day/Hour/Minute/Second][also: Int(oDate) gets the date value, oDate-Int(oDate) gets the time value][WARNING: unlike the Excel sheet function MOD, Mod in VBA rounds floats to integers] Go: Java: JavaScript: ___ [e.g. oDate.setUTCFullYear()/oDate.setFullYear() etc] Kotlin: PHP: Python: oDate.replace() R: Ruby: Rust: Swift: UFL: DateToUnix [Unix dates: seconds since 1970][note: sometimes Unix dates are stated as milliseconds] AutoHotkey: vUnixSec := DateDiff(vDateUTC, 1970, "Seconds") C++: C#: Crystal: Excel: INT((A1-25569)*86400) [WARNING: the calculation uses local, not UTC time][note: 25569 is equivalent to 1970-01-01] Excel VBA: vUnixSec = Int((oDate - 25569) * 86400) [WARNING: the calculation uses local, not UTC time][note: 25569 is equivalent to 1970-01-01] Go: Java: JavaScript: vUnixSec = Math.floor(oDate.getTime()/1000) Kotlin: PHP: Python: vUnixSec = (oDate.astimezone(datetime.timezone.utc)-datetime.datetime.fromtimestamp(0, datetime.timezone.utc)).total_seconds() [also: vUnixSec = (oDate.astimezone(datetime.timezone.utc)-datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc)).total_seconds()] R: Ruby: Rust: Swift: UFL: UnixToDate [Unix dates: seconds since 1970][note: sometimes Unix dates are stated as milliseconds] AutoHotkey: vDate := DateAdd(1970, vUnixSec, "Seconds") C++: C#: Crystal: Excel: 25569+(A1/86400) [WARNING: the calculation uses local, not UTC time][note: 25569 is equivalent to 1970-01-01] Excel VBA: DateSerial(1970, 1, 1) + (vUnixSec / 86400) [WARNING: the calculation uses local, not UTC time] Go: Java: JavaScript: oDate = new Date(vUnixSec*1000) Kotlin: PHP: Python: oDate = datetime.datetime.fromtimestamp(vUnixSec) R: Ruby: Rust: Swift:

Notes:

Time Zones: If using an online programming language compiler/interpreter, it may report 'UTC', and not your local time zone. Some time zone information may be specific to the operating system (e.g. Windows-specific). It can be best to think of dates as a UTC time and a location. To display a date in a time zone, you query: for this UTC time, at this location, what was the time zone offset, and was DST (daylight saving time) in force. Time zones can be thought of as having 4 names. A location, a general name, a non-DST name, a DST name. E.g. Europe/London, 'British Time' (BT), Greenwich Mean Time (GMT) (UTC), British Summer Time (BST) (UTC+1). E.g. America/New_York, Eastern Time (ET), Eastern Standard Time (EST) (UTC-5), Eastern Daylight Time (EDT) (UTC-4). E.g. America/Chicago, Central Time (CT), Central Standard Time (CST) (UTC-6), Central Daylight Time (CDT) (UTC-5). E.g. America/Denver, Mountain Time (MT), Mountain Standard Time (MST) (UTC-7), Mountain Daylight Time (MDT) (UTC-6). E.g. America/Los_Angeles, Pacific Time (PT), Pacific Standard Time (PST) (UTC-8), Pacific Daylight Time (PDT) (UTC-7). Phoenix, Arizona uses Mountain Standard Time (MST) (UTC-7) all year round, it doesn't observe DST. The UK uses Greenwich Mean Time (GMT) (UTC) for 5 months of the year (late Oct-late Mar). The UK uses British Summer Time (BST) (UTC+1) for 7 months of the year (late Mar-late Oct). In US time zones, 'S' stands for 'Standard', i.e. non-DST. In UK time zones, 'S' stands for 'Summer', i.e. DST. Using toLocaleString to format dates as 'yyyy-MM-dd HH:mm:ss' or 'yyyy-MM-ddTHH:mm:ss.000Z': It can be useful to format a date like so: 'yyyy-MM-dd HH:mm:ss'. Such dates are easily sorted, and are well understood internationally. The following 2 examples, ISO and locale, give values that are almost 'yyyy-MM-dd HH:mm:ss'. ISO string: E.g. new Date().toISOString() E.g. new Date(Date.UTC(2006, 5-1, 4, 3, 2, 1)).toISOString() This gives a date in the UTC time zone e.g. '2006-05-04T03:02:01.000Z'. locale string: E.g. new Date().toLocaleString("en-CA-u-hc-h23", {weekday:"short", year:"numeric", month:"2-digit", day:"2-digit", hour:"2-digit", minute:"2-digit", second:"2-digit", timeZoneName:"longOffset"}) E.g. new Date(Date.UTC(2006, 5-1, 4, 3, 2, 1)).toLocaleString("en-CA-u-hc-h23", {weekday:"short", year:"numeric", month:"2-digit", day:"2-digit", hour:"2-digit", minute:"2-digit", second:"2-digit", timeZoneName:"longOffset"}) E.g. new Date(Date.UTC(2006, 5-1, 4, 3, 2, 1)).toLocaleString("en-CA-u-hc-h23", {timezone:"Europe/London", weekday:"short", year:"numeric", month:"2-digit", day:"2-digit", hour:"2-digit", minute:"2-digit", second:"2-digit", timeZoneName:"longOffset"}) This gives a date in the specified time zone (or the local time zone if 'timezone' is omitted) e.g. 'Thu, 2006-05-04, 04:02:01 GMT+01:00'. Note: there is no guarantee that the format won't change in future. Background: I was looking for a 'default' BCP 47 tag, to use with toLocaleString(), that would convert dates to ISO format, and perhaps a variant that used English weekday/month names. Unfortunately, it appears that none currently exists (Dec 2023). The closest I could find were: af, lt, sv, en-CA. Afrikaans, Lithuanian, Swedish, and English (Canada) respectively. Unfortunately, although en-CA used ISO dates, it used 12-hour time, however, this could be fixed by appending '-u-hc-h23', to give: 'en-CA-u-hc-h23'. Note: 'h23' is used, indicating hours 0-23, not 'h24'. Preferred algorithm for adding/subtracting years/months: My preferred algorithm for adding/subtracting years/months, works as follows: Adding/subtracting months, always round down if the date doesn't exist: E.g. Oct 31 + 1 month = 'Nov 31', which doesn't exist, so round down to Nov 30. E.g. Dec 31 - 1 month = 'Nov 31', which doesn't exist, so round down to Nov 30. Adding/subtracting years, always round down if the date doesn't exist: E.g. Feb 29 + 1 year = 'Feb 29', which doesn't exist, so round down to Feb 28. E.g. Feb 29 - 1 year = 'Feb 29', which doesn't exist, so round down to Feb 28. One benefit of this approach is that you know which month you will end up in, it's simple: If you are in January, and you 'add one month', you will end up in February. If you are in February, and you 'subtract one month', you will end up in January. This algorithm is equivalent to the following: ● Microsoft Excel's EDATE function. ● Microsoft Excel VBA's DateAdd function (with 'm'/'yyyy' options). ● Microsoft Windows's SysDateTimePick32 controls. This algorithm differs from: ● JavaScript's setUTCMonth/setMonth methods. Preferred algorithm for counting months between 2 dates: My preferred algorithm for counting the complete months between 2 dates, works as follows: E.g. 2006-05-04 versus 2006-03-14. At first glance, 2006-05 v. 2006-03, the difference is 2 months. Now check the rest of the date (D/H/M/S/milliseconds). The days of the month: 4 v. 14, 4 < 14, so subtract 1 from the total month count. The result is a difference of 1 month. I.e. 14 March to 4 May, is 2 months minus 10 days, hence 1 complete month. E.g. 2006-05-14 versus 2006-03-04. At first glance, 2006-05 v. 2006-03, the difference is 2 months. Now check the rest of the date (D/H/M/S/milliseconds). The days of the month: 4 v. 14, 14 > 4, so leave the month count unchanged. The result is a difference of 2 months. I.e. 4 March to 14 May, is 2 months and 10 days, hence 2 complete months. In general: Compare the year and month values to get a month count. Then compare the rest of the date, and either subtract a month, or leave the value unchanged. Weekdays Sometimes 'weekday' means Mon/Tue/Wed/Thu/Fri but not Sat/Sun. Sometimes 'weekday' means any day of the week (Mon/Tue/Wed/Thu/Fri/Sat/Sun). AM/PM 24-hour time, translates to 12-hour time like so: 0 -> 12 AM 1-11 -> 1-11 AM 12 -> 12 PM 13-23 -> 1-11 PM Note: 1-11 *AM*, is followed by 12 *PM*. Note: 1-11 *PM*, is followed by 12 *AM*. Leap Years Using the Gregorian calendar: To determine whether a year is a leap year or not: 4Y AND (100N OR 400Y): Where 4Y means divisible by 4. Where 100N means not divisible by 100. Where 400Y means divisible by 400. To be a leap year, it must pass 4Y, and pass either 100N or 400Y. Some example years: 1900 4Y 100Y 400N: passes 4Y, fails 100N, fails 400Y, NOT leap. 2000 4Y 100Y 400Y: passes 4Y, fails 100N, but passes 400Y, IS leap. 2001 4N 100N 400N: fails 4Y, NOT leap. 2004 4Y 100Y 400N: passes 4Y, passes 100N, IS leap. Century examples: Are leap: 1600, 2000, 2400. Aren't leap: 1700, 1800, 1900, 2100, 2200, 2300. Combining dates and milliseconds Beware when combining bits of dates that were obtained at different times. Problem: Let's say the time is noon. 12:00:00. At 12:00:00.950, you get the time (12:00:00). At 12:00:00.970, you get the milliseconds (970). That gives: 12:00:00.970. = At 12:00:00.990, you get the time (12:00:00). At 12:00:01.010, you get the milliseconds (010). That gives: 12:00:00.010. You now have 2 'dates' that are out of sequence. Solution: Let's say the time is noon. 12:00:00. At 12:00:00.950, you get the time (12:00:00). At 12:00:00.970, you get the milliseconds (970). At 12:00:00.990, you get the time (12:00:00). That gives: 12:00:00.970. The time values matched (both 12:00:00), so we know the combined time is reliable. = At 12:00:01.010, you get the milliseconds (010). At 12:00:01.030, you get the time (12:00:01). The current time (12:00:01) and the previous time (12:00:00) don't match, so try again: = At 12:00:01.050, you get the milliseconds (050). At 12:00:01.070, you get the time (12:00:01). That gives: 12:00:01.050. The time values matched (both 12:00:01), so we know the combined time is reliable. Lower Priority The only item currently marked as lower priority is DateGetEra (e.g. return AD). Another relatively low priority item is DateGetYDay. One use is to schedule something every n days.

Links:

[AutoHotkey] FormatTime - Syntax & Usage | AutoHotkey v2 [C++] [C#] [Crystal] [Excel] Format numbers as dates or times - Microsoft Support Excel incorrectly assumes that the year 1900 is a leap year - Microsoft 365 Apps | Microsoft Learn [Excel VBA] Format function (Visual Basic for Applications) | Microsoft Learn Format or DatePar functions return a wrong week number for a date - Microsoft 365 Apps | Microsoft Learn [Format/DatePart] [Go] [Java] [JavaScript] Intl.DateTimeFormat() constructor - JavaScript | MDN [Kotlin] [PHP] [Python] strftime(3) — manpages-dev — Debian bookworm — Debian Manpages datetime — Basic date and time types — Python 3.12.1 documentation [R] [Ruby] [Rust] [Swift]

Original Outline:

note: this is the original outline on which this page was based note: further items were since added new date: UTC new date: local new date: any time zone new date: tick count (e.g. milliseconds since program started, milliseconds since PC switched on) date to string: UTC string date to string: local date string with time zone stated date to string: 14-digit string (yyyyMMddHHmmss) date to string: 6-member array (yyyy, MM, dd, HH, mm, ss) date to string: using similar formatting to AutoHotkey's FormatTime, and the Winapi's GetDateFormat/GetTimeFormat date to number: get week number (week containing January 1st is numbered week 1) date to number: get ISO week number (week containing the first Thursday of the year is numbered week 1) date add: days/hours/minutes/seconds/milliseconds date add: years/months (same algorithm as Microsoft SysDateTimePick32 controls) date diff: difference in days/hours/minutes/seconds/milliseconds date diff: difference in years/months (and handling tiebreaks) date is valid: validate string calculate key dates: Easter calculate key dates: nearest weekday to a specific date calculate key dates: nth weekday in range (e.g. 1st/2nd/3rd/4th/last Sunday of the month)