
Motivation.
Epic Epoch.
Basic Delphi Usage.
... uses ... System.DateUtils, ... procedure TForm1.WebButton2Click(Sender: TObject); procedure TestTDateTime(aDateTime: TDateTime); begin console.log('TDateTime Value: '+FloatToStrF(ADateTime,ffNumber,5,3)); console.log('TDateTime = 0.0: '+DateTimeToStr(0.0)); console.log('Favourite DateTime Format: ' +FormatDateTime('yyyy-mm-dd hh:nn:ss', aDateTime)); console.log('Second Favourite DateTime Format: ' +FormatDateTime('yyyy-mmm-dd hh:nn:ss', aDateTime)); console.log('Third Favourite DateTime Format: ' +FormatDateTime('yyyy-mmm-dd (ddd) hh:nn:ss', aDateTime)); console.log('Short DateTime Format: ' +FormatDateTime('ddddd t', aDateTime)); console.log('Long DateTime Format: ' +FormatDateTime('ddddd tt', aDateTime)); console.log('Short Date Format Settings: ' +FormatSettings.ShortDateFormat); console.log('Long Date Format Settings: ' +FormatSettings.LongDateFormat); console.log('Date Separator Settings: ' +FormatSettings.DateSeparator); console.log('Short Time Format Settings: ' +FormatSettings.ShortTimeFormat); console.log('Long Time Format Settings: ' +FormatSettings.LongTimeFormat); console.log('Time Separator Settings: ' +FormatSettings.TimeSeparator); console.log('First Day of Month: ' +FormatDateTime('yyyy-mmm-dd', StartOfTheMonth(ADateTime))); console.log('Last Day of Month: ' +FormatDateTime('yyyy-mmm-dd', EndOfTheMonth(ADateTime))); console.log('First Day of Prior Month: ' +FormatDateTime('yyyy-mmm-dd', StartOfTheMonth(IncMonth(ADateTime,-1)))); console.log('Last Day of Prior Month: ' +FormatDateTime('yyyy-mmm-dd', EndOfTheMonth(IncMonth(ADateTime,-1)))); console.log('First Day of Next Month: ' +FormatDateTime('yyyy-mmm-dd', StartOfTheMonth(IncMonth(ADateTime,+1)))); console.log('Last Day of Next Month: ' +FormatDateTime('yyyy-mmm-dd', EndOfTheMonth(IncMonth(ADateTime,+1)))); console.log('Day of Year: ' +IntToStr(DayOfTheYear(aDateTime))); console.log('Day of Week: ' +FormatDateTime('dddd', ADateTime)); // Week starts on Monday console.log('ISO Day of Week Number: ' +IntToStr(DayoftheWeek(ADateTime))); console.log('ISO Week Number: ' +IntToStr(WeekOfTheYear(aDateTime))); console.log('ISO First Day of Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',StartOfTheWeek(aDateTime))); console.log('ISO Last Day of Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',EndOfTheWeek(aDateTime))); console.log('ISO First Day of Prior Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',StartOfTheWeek(aDateTime-7))); console.log('ISO Last Day of Prior Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',EndOfTheWeek(aDateTime-7))); console.log('ISO First Day of Next Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',StartOfTheWeek(aDateTime+7))); console.log('ISO Last Day of Next Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',EndOfTheWeek(aDateTime+7))); // Week starts on Sunday console.log('non-ISO Day of Week Number: ' +IntToStr(DayofWeek(ADateTime))); // If Sunday, use Monday instead because WeekOfTheYear doesn't know about Sunday weeks console.log('non-ISO Week Number: ' +IntToStr(WeekOfTheYear(aDateTime+Trunc(DayOftheWeek(ADateTime)/7)))); console.log('non-ISO First Day of Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',aDateTime + 1 - DayOfWeek(aDateTime))); console.log('non-ISO Last Day of Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',aDateTime + 7 - DayOfWeek(aDateTime))); console.log('non-ISO First Day of Prior Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',aDateTime - 6 - DayOfWeek(aDateTime))); console.log('non-ISO Last Day of Prior Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',aDateTime - DayOfWeek(aDateTime))); console.log('non-ISO First Day of Next Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',aDateTime + 8 - DayOfWeek(aDateTime))); console.log('non-ISO Last Day of Next Week: ' +FormatDateTime('yyyy-mmm-dd (ddd)',aDateTime +14 - DayOfWeek(aDateTime))); console.log('Calculating a day duration: ' +IntToStr(DaysBetween(Today,EncodeDate(1971,05,25)))); console.log('Calculating a time duration: ' +IntToStr(MillisecondsBetween(Now,Now-1))+'ms'); end; begin TestTDateTime(EncodeDateTime(2021, 12, 26, 12, 13, 14, 0)); // A Sunday TestTDateTime(EncodeDateTime(2022, 1, 2, 12, 13, 14, 0)); // Also a Sunday TestTDateTime(EncodeDateTime(2022, 1, 9, 12, 13, 14, 0)); // Yep, another Sunday end;
2021-Dec-26 (Sunday) |
2022-Jan-02 (Sunday) |
2022-Jan-09 (Sunday) |
|
TDateTime Value |
44,556.509 |
44,563.509 |
44,570.509 |
TDateTime = 0.0 |
1899-12-30 |
1899-12-30 |
1899-12-30 |
Favourite DateTime Format |
2021-12-26 12:13:14 |
2022-01-02 12:13:14 |
2022-01-09 12:13:14 |
Second Favourite DateTime Format |
2021-Dec-26 12:13:14 |
2022-Jan-02 12:13:14 |
2022-Jan-09 12:13:14 |
Third Favourite DateTime Format |
2021-Dec-26 (Sun) 12:13:14 |
2022-Jan-02 (Sun) 12:13:14 |
2022-Jan-09 (Sun) 12:13:14 |
Short DateTime Format |
2021-12-26 12:13 |
2022-01-02 12:13 |
2022-01-09 12:13 |
Long DateTime Format |
2021-12-26 12:13:14 |
2022-01-02 12:13:14 |
2022-01-09 12:13:14 |
Short Date Format Settings |
yyyy-mm-dd |
yyyy-mm-dd |
yyyy-mm-dd |
Long Date Format Settings |
ddd, yyyy-mm-dd |
ddd, yyyy-mm-dd |
ddd, yyyy-mm-dd |
Date Separator Settings |
- |
- |
- |
Short Time Format Settings |
hh:nn |
hh:nn |
hh:nn |
Long Time Format Settings |
hh:nn:ss |
hh:nn:ss |
hh:nn:ss |
Time Separator Settings |
: |
: |
: |
First Day of Month |
2021-Dec-01 |
2022-Jan-01 |
2022-Jan-01 |
Last Day of Month |
2021-Dec-31 |
2022-Jan-31 |
2022-Jan-31 |
First Day of Prior Month |
2021-Nov-01 |
2021-Dec-01 |
2021-Dec-01 |
Last Day of Prior Month |
2021-Nov-30 |
2021-Dec-31 |
2021-Dec-31 |
First Day of Next Month |
2022-Jan-01 |
2022-Feb-01 |
2022-Feb-01 |
Last Day of Next Month |
2022-Jan-31 |
2022-Feb-28 |
2022-Feb-28 |
Day of Year |
360 |
2 |
9 |
Day of Week |
Sunday |
Sunday |
Sunday |
ISO Day of Week Number |
7 |
7 |
7 |
ISO Week Number |
51 |
52 |
1 |
ISO First Day of Week |
2021-Dec-20 (Mon) |
2021-Dec-27 (Mon) |
2022-Jan-03 (Mon) |
ISO Last Day of Week |
2021-Dec-26 (Sun) |
2022-Jan-02 (Sun) |
2022-Jan-09 (Sun) |
ISO First Day of Prior Week |
2021-Dec-13 (Mon) |
2021-Dec-20 (Mon) |
2021-Dec-27 (Mon) |
ISO Last Day of Prior Week |
2021-Dec-19 (Sun) |
2021-Dec-26 (Sun) |
2022-Jan-02 (Sun) |
ISO First Day of Next Week |
2021-Dec-27 (Mon) |
2022-Jan-03 (Mon) |
2022-Jan-10 (Mon) |
ISO Last Day of Next Week |
2022-Jan-02 (Sun) |
2022-Jan-09 (Sun) |
2022-Jan-16 (Sun) |
non-ISO Day of Week Number |
1 |
1 |
1 |
non-ISO Week Number |
52 |
1 |
2 |
non-ISO First Day of This Week |
2021-Dec-26 (Sun) |
2022-Jan-02 (Sun) |
2022-Jan-09 (Sun) |
non-ISO Last day of This Week |
2022-Jan-01 (Sat) |
2022-Jan-08 (Sat) |
2022-Jan-15 (Sat) |
non-ISO First Day of Prior Week |
2021-Dec-19 (Sun) |
2021-Dec-26 (Sun) |
2022-Jan-02 (Sun) |
non-ISO Last Day of Prior Week |
2022-Jan-01 (Sat) |
2022-Jan-01 (Sat) |
2022-Jan-08 (Sat) |
non-ISO First Day of Next Week |
2022-Jan-02 (Sun) |
2022-Jan-09 (Sun) |
2022-Jan-16 (Sun) |
non-ISO Last Day of Next Week |
2022-Jan-08 (Sat) |
2022-Jan-15 (Sat) |
2022-Jan-22 (Sat) |
Calculating a day duration |
18626 |
18626 |
18626 |
non-ISO Last day of next Week |
86400000ms |
86400000ms |
86400000ms |
- Regardless of development platform or programming language, it is generally considered good practice to always use the available functions provided by your environment when dealing with datetime values. In part, this is to save you from the headaches that come with having to think about leap years or how many days are in a month. This is also working with the assumption that system_function(a_valid_date) -> another_valid_date. Numerous errors can creep in when you start fiddling with things. This is not always easy though, and the further you stray from "convention" the more likely you are to run into problems. Even in my examples above, there's more fiddling than I'd like with those first/last day of week calculations. Fortunately, I've not yet run across anyone who has argued against weeks having seven days, so this is reasonably safe. One of the few instances where there aren't numerous opinions.
- Speaking of which, ISO8601 seems at first to be a strict standard in many respects, but on closer inspection it isn't really all that strict at all. Except, curiously, for the start of the week, which it unequivocally states is Monday. However, in my part of the world (Canada) I honestly can't recall ever seeing a printed calendar that didn't have Sunday on the left and Saturday on the right. Which means, indirectly, the week starts on Sunday. And everywhere I've worked, and everyone I've worked with, would likely have the same opinion. Yet, at another location, perhaps in another country or continent, the exact opposite may be the case. And while I've never run across this situation personally, I've read that in some places the first day of the week can be Saturday. More specifically, some ethnic groups (regardless of physical location) may prefer this. So.... ??! This can be a real problem. Delphi itself even has different variations of its functions. One set of variations offers up the ability of passing in TDateTime values instead of the constituent parts (the "the" functions). Another variation relates to whether Sunday = 1 or Monday = 1. Tricky, tricky. Whatever situation you're faced with, there's a need to be careful about this and be sure that you use the same functions (and conventions) consistently, if only for your own sanity.
- Similarly, week numbers can sometimes be a cause for confusion. A large number of years ago, I remember visiting an office in early January when staff were checking out the latest swag from two separate billion-dollar-plus agriculture vendors, both from the same northern-European country that rather prides itself in its agricultural prowess. The swag in this case included very large wall calendars, showing the entire year at a glance. With equal parts horror and humor, it turned out that the calendars from the different vendors didn't have the same week numbers assigned. I think, collectively as a planet, we've since come to agree that Week #1 is considered the first week that has a Thursday in it. ISO8601 prevails. Though this is more of a "recent" realization that people have arrived at, and isn't necessarily implemented the same way everywhere. That's what we're going with here though. Conveniently, this isn't really in conflict really with my point (2) above. We'll just have to argue about which week Sundays fall into.
- TDateTime has millisecond precision, if you're interested in that level of detail. However, some systems (databases, for example) may have more precision. DB2 timestamps record microseconds (six digits instead of three), as do others. So this is something to be mindful of when moving data around, particularly if you're comparing dates looking for exact matches. And especially when the database itself generates timestamps, which we'll cover in more detail shortly. Sometimes this also happens behind the scenes. This is why, if you're using conventional Delphi DB components to access a database, timestamps are truncated after seconds. To ensure that the components and the database are always using the same precision.
- An example of ISO8601 being perhaps less than rigid is that dates can be expressed as either YYYY-MM-DD or YYYYMMDD - what they refer to as enhanced vs. basic. Nothing like a good standard to not take sides! So when there is a claim that something is ISO8601 compliant, you have to really not put too much faith in that alone as it may mean different things to different people. And yes, I'm looking at you, TXDataWebDataset.SetJSONData. Or FireDAC, equally to blame I suppose! As with anything else, these sorts of things have to be tested and you have to keep an eye out not only for variations in formats but also that when things are working, that they aren't causing other problems downstream. One part of a series of function calls may happily tolerate slight variations in a format whereas another will be stopped cold.
- Users have preferences. Customers have preferences. Developers have preferences. Rarely are these in alignment. And sometimes the deciding factor isn't related to standards or coding or any of these preferences, but rather the dreaded "business rules" when someone decided, likely decades ago, that "This is the way" for that organization. It is for this reason that I've gotten into the habit of providing a general configuration option in my projects, where different periods (weeks, months, fiscal years, quarters, seasons, payroll periods, stat holidays, etc.) can be arbitrarily defined and then deployed consistently across an organization, at least within the confines of my projects. At least when they mess it up (which they also consistently do, nearly every year!), it is messed up consistently for everyone. Not sure if that has been a net benefit or not? Point being, though, that with a little (OK, a LOT of) luck your users or your customers will hopefully be internally consistent with this kind of thing, at least within their own organization.
- Then there is the concept of "internationalization". Let's call it that for now, anyway. Sometimes it's called "localization". Not confusing at all. The idea that wherever you are in the world, your region (typically your country) has some generally-agreed-upon ideas about what the date format should be, what the first day of the week should be, what the names of the days of the week and months of the year are (with variations for official languages in the region), the equivalent shorter names for days of the week and months of the year, how "medium" and "long" dates should be expressed, and so on. Often you'll see software settings in applications where you can select a different region, if you happen to find your own region's preferred default settings aren't to your liking. I suspect Denmark is likely a more popular regional selection than it otherwise would be, for this very reason. One (very good!) school of thought is that as a developer you should use this system exclusively, giving good defaults to all users globally, with the option for them to use different settings if they choose. Noble even, perhaps. But perhaps misplaced.
- And finally, completely contrary to (7) above, is that users in a particular region may not wish to use the defaults for their region, or any region. Even if they happen to live in Denmark! And this system is certainly not without flaws of its own. For example, I regularly use a Fedora desktop system with FireFox, Thunderbird (BetterBird, actually), and Google Chrome. It seems they all (sort of) rely on the Fedora locale to do their thing. Which Fedora itself does a very poor job of in terms of offering any kind of flexibility. And thus everything downstream from there gets progressively worse. Even Chrome and Firefox may not agree on the particular options using the same system, which can be infuriating at times.
procedure TForm1.WebFormCreate(Sender: TObject); begin asm var fp1 = flatpickr('#WebEdit1', { appendTo: WebHTMLDiv1, inline: true, weekNumbers: true, locale: { firstDayOfWeek:0, // Sunday } }); var fp2 = flatpickr('#WebEdit2', { appendTo: WebHTMLDiv2, inline: true, weekNumbers: true, locale: { firstDayOfWeek:1, // Monday } }); end; end;

Timezones, UTC, Local Time, and Offsets.
Function GetLocalTimeOffset : Integer; begin Result:=TJSDate.New.getTimezoneOffset(); end;
procedure TForm1.WebButton1Click(Sender: TObject); var tz_name: String; tz_short: String; begin asm tz_name = Intl.DateTimeFormat().resolvedOptions().timeZone; tz_short = new Date().toLocaleString('en', {timeZoneName:'short'}).split(' ').pop(); end; console.log('Local Time: '+FormatDateTime('yyyy-mmm-dd (ddd) hh:nn:ss', Now)); console.log('Local Timezone Name: '+tz_name); console.log('Local Timezone Short: '+tz_short); console.log('UTC Offset: '+IntToStr(TJSDate.new.gettimezoneoffset())+' minutes'); console.log('UTC: '+FormatDateTime('yyyy-mmm-dd (ddd) hh:nn:ss', LocalTimeToUniversal(Now))); console.log('UTC to Local Time: '+FormatDateTime('yyyy-mmm-dd (ddd) hh:nn:ss',UniversalTimeToLocal(EncodeDateTime(2022,5,22,6,0,0,0)))); end; // console.log output: Local Time: 2022-May-21 (Sat) 22:40:14 Local Timezone Name: America/Vancouver Local Timezone Short: PDT UTC Offset: 420 minutes UTC: 2022-May-22 (Sun) 05:40:14 UTC to Local Time: 2022-May-21 (Sat) 23:00:00
Server-Side Sidebar.
select timezone(TICKETTIMESTAMP, :SERVERTZ, :LOCALTZ) TICKETLOCALTIMESTAMP from TICKETS where USER='frank'
select convert_tz(TICKETTIMESTAMP, :SERVERTZ, :LOCALTZ) TICKETLOCALTIMESTAMP from TICKETS where USER='frank'
function MyService.GetReport(Parameters:String):TStream; var ClientTimeZone: TBundledTimeZone; ServerTime:TDateTime; ClientTime:TDateTime; GlobalTime:TDateTime; TimeZone: String; begin ... // TimeZone value is retrieved from the JWT ... ClientTimeZone :=TBundledTimeZone.GetTimeZone(TimeZone); ServerTime := Now; GlobalTime := TTimeZone.Local.ToUniversalTime(ServerTime); ClientTime := ClientTimeZone.ToLocalTime(GlobalTime); Report.FooterLeft.Caption := FormatDateTime('yyyy-mmm-dd (ddd) hh:nn:ss', ClientTime); ... end;
Luxon Enters the Chat.
procedure TForm1.WebButton4Click(Sender: TObject); begin asm function testLuxon(aDate) { console.log('Date Value: '+aDate); console.log('Favourite DateTime Format: ' +aDate.toFormat('yyyy-LL-dd HH:mm:ss')); console.log('Second Favourite DateTime Format: ' +aDate.toFormat('yyyy-LLL-dd HH:mm:ss')); console.log('Third Favourite DateTime Format: ' +aDate.toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')); console.log('Shortest DateTime Format: ' +aDate.toFormat('f')); console.log('Shorter DateTime Format: ' +aDate.toFormat('ff')); console.log('Shortish DateTime Format: ' +aDate.toFormat('fff')); console.log('Short DateTime Format: ' +aDate.toFormat('ffff')); console.log('Long DateTime Format: ' +aDate.toFormat('F')); console.log('Longish DateTime Format: ' +aDate.toFormat('FF')); console.log('Longer DateTime Format: ' +aDate.toFormat('FFF')); console.log('Longest DateTime Format: ' +aDate.toFormat('FFFF')); console.log('First Day of Month: '+aDate.startOf('month').toFormat('yyyy-LLL-dd')); console.log('Last Day of Month: '+aDate.endOf('month').toFormat('yyyy-LLL-dd')); console.log('First Day of Prior Month: '+aDate.plus({months: -1}).startOf('month').toFormat('yyyy-LLL-dd')); console.log('Last Day of Prior Month: '+aDate.plus({months: -1}).endOf('month').toFormat('yyyy-LLL-dd')); console.log('First Day of Next Month: '+aDate.plus({months: 1}).startOf('month').toFormat('yyyy-LLL-dd')); console.log('Last Day of Next Month: '+aDate.plus({months: 1}).endOf('month').toFormat('yyyy-LLL-dd')); console.log('Day of Week: ' +aDate.toFormat('cccc')); console.log('Day of Year: ' +aDate.toFormat('o')); // Start of Week = Monday console.log('ISO Day of Week Number: ' +aDate.weekday); console.log('ISO Week Number: ' +aDate.weekNumber); console.log('ISO First Day of Week: ' +aDate.startOf('week').toFormat('yyyy-LLL-dd (ccc)')); console.log('ISO Last Day of Week: ' +aDate.endOf('week').toFormat('yyyy-LLL-dd (ccc)')); console.log('ISO First Day of Prior Week: ' +aDate.plus({weeks: -1}).startOf('week').toFormat('yyyy-LLL-dd (ccc)')); console.log('ISO Last Day of Prior Week: ' +aDate.plus({weeks: -1}).endOf('week').toFormat('yyyy-LLL-dd (ccc)')); console.log('ISO First Day of Next Week: ' +aDate.plus({weeks: 1}).startOf('week').toFormat('yyyy-LLL-dd (ccc)')); console.log('ISO Last Day of Next Week: ' +aDate.plus({weeks: 1}).endOf('week').toFormat('yyyy-LLL-dd (ccc)')); // Start of Week = Sunday console.log('non-ISO Day of Week: ' +aDate.toFormat('cccc')); // Mon=1,Sun=7 >>> Sun=1, Sat=7 console.log('non-ISO Day of Week Number: ' +((aDate.weekday % 7) + 1)); // If Sunday, get weekNumber for Monday console.log('non-ISO Week Number: ' +aDate.plus({days: Math.trunc(aDate.weekday / 7)}).weekNumber); console.log('non-ISO Day of Year: ' +aDate.toFormat('o')); console.log('non-ISO First Day of Week: ' +aDate.plus({days: + 1 - ((aDate.weekday % 7) + 1)}).toFormat('yyyy-LLL-dd (ccc)')); console.log('non-ISO Last Day of Week: ' +aDate.plus({days: + 7 - ((aDate.weekday % 7) + 1)}).toFormat('yyyy-LLL-dd (ccc)')); console.log('non-ISO First Day of Prior Week: ' +aDate.plus({days: - 6 - ((aDate.weekday % 7) + 1)}).toFormat('yyyy-LLL-dd (ccc)')); console.log('non-ISO Last Day of Prior Week: ' +aDate.plus({days: - ((aDate.weekday % 7) + 1)}).toFormat('yyyy-LLL-dd (ccc)')); console.log('non-ISO First Day of Next Week: ' +aDate.plus({days: + 8 - ((aDate.weekday % 7) + 1)}).toFormat('yyyy-LLL-dd (ccc)')); console.log('non-ISO Last Day of Next Week: ' +aDate.plus({days: +14 - ((aDate.weekday % 7) + 1)}).toFormat('yyyy-LLL-dd (ccc)')); console.log('Calculating a day duration: '+Math.trunc(luxon.DateTime.now().diff(luxon.DateTime.local(1971,5,25,0,0,0,0), 'days').days)); console.log('Calculating a time duration: '+luxon.DateTime.now().diff(luxon.DateTime.now().plus({days: -1}))+'ms'); } testLuxon(luxon.DateTime.local(2021, 12, 26, 12, 13, 14, 0)); testLuxon(luxon.DateTime.local(2022, 1, 2, 12, 13, 14, 0)); testLuxon(luxon.DateTime.local(2022, 1, 9, 12, 13, 14, 0)); end; end;
2021-Dec-26 (Sunday) |
2022-Jan-02 (Sunday) |
2022-Jan-09 (Sunday) |
|
Date Value |
1640549594000 |
1641154394000 |
1641759194000 |
Favourite DateTime Format |
2021-12-26 12:13:14 |
2022-01-02 12:13:14 |
2022-01-09 12:13:14 |
Second Favourite DateTime Format |
2021-Dec-26 12:13:14 |
2022-Jan-02 12:13:14 |
2022-Jan-09 12:13:14 |
Third Favourite DateTime Format |
2021-Dec-26 (Sun) 12:13:14 |
2022-Jan-02 (Sun) 12:13:14 |
2022-Jan-09 (Sun) 12:13:14 |
Shortest DateTime Format |
12/26/2021, 12:13 PM |
1/2/2022, 12:13 PM |
1/9/2022, 12:13 PM |
Shorter DateTime Format |
Dec 26, 2021, 12:13 PM |
Jan 2, 2022, 12:13 PM |
2022-01-09 12:13:14 |
Shortish DateTime Format |
December 26, 2021, 12:13 PM PST |
January 2, 2022, 12:13 PM PST |
January 9, 2022, 12:13 PM PST |
Short DateTime Format |
Sunday, December 26, 2021, 12:13 PM Pacific Standard Time |
Sunday, January 2, 2022, 12:13 PM Pacific Standard Time |
Sunday, January 9, 2022, 12:13 PM Pacific Standard Time |
Long DateTime Format |
12/26/2021, 12:13:14 PM |
1/2/2022, 12:13:14 PM |
1/9/2022, 12:13:14 PM |
Longish DateTime Format |
Dec 26, 2021, 12:13:14 PM |
Jan 2, 2022, 12:13:14 PM |
Jan 9, 2022, 12:13:14 PM |
Longer DateTime Format |
December 26, 2021, 12:13:14 PM PST |
January 2, 2022, 12:13:14 PM PST |
January 9, 2022, 12:13:14 PM PST |
Longest DateTime Format |
Sunday, December 26, 2021, 12:13:14 PM Pacific Standard Time |
Sunday, January 2, 2022, 12:13:14 PM Pacific Standard Time |
Sunday, January 9, 2022, 12:13:14 PM Pacific Standard Time |
First Day of Month |
2021-Dec-01 |
2022-Jan-01 |
2022-Jan-01 |
Last Day of Month |
2021-Dec-31 |
2022-Jan-31 |
2022-Jan-31 |
First Day of Prior Month |
2021-Nov-01 |
2021-Dec-01 |
2021-Dec-01 |
Last Day of Prior Month |
2021-Nov-30 |
2021-Dec-31 |
2021-Dec-31 |
First Day of Next Month |
2022-Jan-01 |
2022-Feb-01 |
2022-Feb-01 |
Last Day of Next Month |
2022-Jan-31 |
2022-Feb-28 |
2022-Feb-28 |
Day of Year |
360 |
2 |
9 |
Day of Week |
Sunday |
Sunday |
Sunday |
ISO Day of Week Number |
7 |
7 |
7 |
ISO Week Number |
51 |
52 |
1 |
ISO First Day of Week |
2021-Dec-20 (Mon) |
2021-Dec-27 (Mon) |
2022-Jan-03 (Mon) |
ISO Last Day of Week |
2021-Dec-26 (Sun) |
2022-Jan-02 (Sun) |
2022-Jan-09 (Sun) |
ISO First Day of Prior Week |
2021-Dec-13 (Mon) |
2021-Dec-20 (Mon) |
2021-Dec-27 (Mon) |
ISO Last Day of Prior Week |
2021-Dec-19 (Sun) |
2021-Dec-26 (Sun) |
2022-Jan-02 (Sun) |
ISO First Day of Next Week |
2021-Dec-27 (Mon) |
2022-Jan-03 (Mon) |
2022-Jan-10 (Mon) |
ISO Last Day of Next Week |
2022-Jan-02 (Sun) |
2022-Jan-09 (Sun) |
2022-Jan-16 (Sun) |
non-ISO Day of Week Number |
1 |
1 |
1 |
non-ISO Week Number |
52 |
1 |
2 |
non-ISO First Day of This Week |
2021-Dec-26 (Sun) |
2022-Jan-02 (Sun) |
2022-Jan-09 (Sun) |
non-ISO Last day of This Week |
2022-Jan-01 (Sat) |
2022-Jan-08 (Sat) |
2022-Jan-15 (Sat) |
non-ISO First Day of Prior Week |
2021-Dec-19 (Sun) |
2021-Dec-26 (Sun) |
2022-Jan-02 (Sun) |
non-ISO Last Day of Prior Week |
2022-Jan-01 (Sat) |
2022-Jan-01 (Sat) |
2022-Jan-08 (Sat) |
non-ISO First Day of Next Week |
2022-Jan-02 (Sun) |
2022-Jan-09 (Sun) |
2022-Jan-16 (Sun) |
non-ISO Last Day of Next Week |
2022-Jan-08 (Sat) |
2022-Jan-15 (Sat) |
2022-Jan-22 (Sat) |
Calculating a day duration |
18626 |
18626 |
18626 |
non-ISO Last day of next Week |
86400000ms |
86400000ms |
86400000ms |
Great. So What Else Can Luxon Do?
asm var vancouver = luxon.DateTime.local(2022, 5, 22, 12, 13, 14, 0); console.log('America/Vancouver: '+vancouver.toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')+' ( timezone = '+vancouver.zoneName+' )'); console.log('America/New_York: '+vancouver.setZone('America/New_York').toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')); console.log('Europe/London: '+vancouver.setZone('Europe/London').toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')); console.log('Europe/Paris: '+vancouver.setZone('Europe/Paris').toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')); console.log('Europe/Kiev: '+vancouver.setZone('Europe/Kiev').toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')); console.log('Asia/Singapore: '+vancouver.setZone('Asia/Singapore').toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')); end; // console.log output: America/Vancouver: 2022-May-22 (Sun) 12:13:14 ( timezone = America/Vancouver ) America/New_York: 2022-May-22 (Sun) 15:13:14 Europe/London: 2022-May-22 (Sun) 20:13:14 Europe/Paris: 2022-May-22 (Sun) 21:13:14 Europe/Kiev: 2022-May-22 (Sun) 22:13:14 Asia/Singapore: 2022-May-23 (Mon) 03:13:14
asm console.log('America/Vancouver: '+vancouver.toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')+' ( timezone = '+vancouver.zoneName+' )'); console.log('UTC: '+vancouver.setZone('utc').toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')); console.log('UTC+1: '+vancouver.setZone('utc+1').toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')); console.log('CET (Central Europe): '+vancouver.setZone('cet').toFormat('yyyy-LLL-dd (ccc) HH:mm:ss')); end; // console.log output: America/Vancouver: 2022-May-22 (Sun) 12:13:14 ( timezone = America/Vancouver ) UTC: 2022-May-22 (Sun) 19:13:14 UTC+1: 2022-May-22 (Sun) 20:13:14 CET (Central Europe): 2022-May-22 (Sun) 21:13:14
asm var start = luxon.DateTime.local(2022, 5, 21, 0, 13, 14); var finish = luxon.DateTime.local(2022, 5, 22, 12, 13, 14); // 36 hours later console.log('start was '+Math.trunc(finish.diff(start, 'minutes').minutes)+' minute(s) ago'); console.log('start was '+Math.trunc(finish.diff(start, 'hours').hours)+' hour(s) ago'); console.log('start was '+Math.trunc(finish.diff(start, 'days').days)+' day(s) ago'); console.log('start was '+JSON.stringify(finish.diff(start, ['days','hours','minutes']).toObject())); console.log('start was '+finish.diff(start, ['days','hours']).toHuman()+' ago'); end; start was 2160 minute(s) ago start was 36 hour(s) ago start was 1 day(s) ago start was {"days":1,"hours":12,"minutes":0} start was 1 day, 12 hours ago
Getting Around.
function TForm1.ConvertTimezone(aDateTime: TDateTime; TZ: String): TDateTime; var ayear, amonth, aday, ahour, aminute, asecond, amillisecond: word; begin DecodeDateTime(aDateTime, ayear, amonth, aday, ahour, aminute, asecond, amillisecond); asm var lDateTime = new luxon.DateTime.local(ayear, amonth, aday, ahour, aminute, asecond, amillisecond).setZone(TZ); ayear = lDateTime.year; amonth = lDateTime.month; aday = lDateTime.day; ahour = lDateTime.hour; aminute = lDateTime.minute; asecond = lDateTime.second; amillisecond = lDateTime.millisecond; end; Result := EncodeDateTime(ayear, amonth, aday, ahour, aminute, asecond, amillisecond); end; procedure TForm1.WebButton1Click(Sender: TObject); var olddate, newdate: TDateTime; begin olddate := EncodeDateTime(2022, 5, 22, 12, 13, 14, 0); newdate := ConvertTimeZone(olddate, 'Europe/Paris'); console.log(FormatDateTime('yyyy-mmm-dd hh:nn:ss',olddate)); console.log(FormatDateTime('yyyy-mmm-dd hh:nn:ss',newdate)); end; // console.log output: 2022-May-22 12:13:14 2022-May-22 21:13:14 function TForm1.HumanDifference(nowDateTime: TDateTime; thenDateTime: TDateTime): String; var ayear, amonth, aday, ahour, aminute, asecond, amillisecond: word; byear, bmonth, bday, bhour, bminute, bsecond, bmillisecond: word; begin DecodeDateTime(nowDateTime, ayear, amonth, aday, ahour, aminute, asecond, amillisecond); DecodeDateTime(thenDateTime, byear, bmonth, bday, bhour, bminute, bsecond, bmillisecond); asm var aDateTime = new luxon.DateTime.local(ayear, amonth, aday, ahour, aminute, asecond, amillisecond); var bDateTime = new luxon.DateTime.local(byear, bmonth, bday, bhour, bminute, bsecond, bmillisecond); Result = aDateTime.diff(bDateTime, ['days','hours']).toHuman()+' ago'; end; end; procedure TForm1.WebButton1Click(Sender: TObject); var olddate, newdate: TDateTime; begin olddate := EncodeDateTime(2022, 5, 21, 06, 13, 14, 0); newdate := EncodeDateTime(2022, 5, 22, 12, 13, 14, 0); // 30 hours later console.log(HumanDifference(newdate, olddate)); end; // console.log output: 1 day, 6 hours ago