Data Science Weekly – Issue 601 (datascienceweekly.substack.com)
1 points by sebg 15m ago 0 comments
Why Graham crackers were invented (allthatsinteresting.com)
1 points by bookofjoe 17m ago 0 comments
Why are 2025/05/28 and 2025-05-28 different days in JavaScript?
137 brandon_bot 144 5/28/2025, 7:09:31 AM brandondong.github.io ↗
https://en.wikipedia.org/wiki/ISO_8601
Handed down by the ISO, The Great Compromise allows YYYY-MM-DD (or YYYYMMDD if you're in a hurry) but the version with slashes I'd find ambiguous and upsetting, especially early in the month.
The standard is good, and you can get it from `date -I`. Hell mend anyone who messes with the delimiters or writes the year in octal or any other heresy.
(Example - you want to know if a person is old enough to buy cigarettes, and you need to store a birthday that you can compare against the current day to see if they're legally 18 - if you store an epoch at UTC, do you store the time of day they were born? That's not the way the law works. Do you store midnight UTC? If they're currently in NY, can they but cigarettes at 7pm the day before their birthday because they're currently 18 in London?)
Sometimes you need a logical calendar date, not a point in time in the history of the universe.
If you were born in the US, can you buy cigarettes at 12:00 am on your 18th birthday in London?
I’ve never heard of age verification laws caring what timezone you were born in. In fact, you couldn’t even pinpoint this from many people’s ID cards. Plenty of US states span multiple time zones, and I wouldn’t be that surprised if there were a maternity ward out there sitting on a TZ line.
I grew up in a country where you could legally buy beer with 16 and and hard alcohol with 18. So if the answer to "when should someone be allowed to choose to drink alcohol" has a variance of multiple years between countries who cares about a day or two.
Certainly if you want to store birth dates and do age verification there is no point bothering with these issues, just store calendar date. Trivial to get date for age limit purposes.
ISO 8601 allows for 2 or 6 digit years. Truncating to 2 is just incorrect, and 6 digits is absurd. And you can read the RFC without paying ISO - and you can discuss the RFC with people who have also read it instead of relying on people using the Wikipedia page to interpret and explain ISO 8601.
I have a scheduling service at work and I keep getting requests for implementing ISO 8601 timestamps but I ignore them. RFC3339 is the way forward.
Just found a random link to it with an image search:
https://gyazo.com/d8517f72e24c38f055e17182842b991c/max_size/...
ISO 8601 does have some strange formats...
https://ijmacd.github.io/rfc3339-iso8601/
Not that I’ve ever really had cause to use it in anger, but I like the idea of ISO week dates.
Effectively, the ISO weak year (often differs from the calendar year in the last week of December / first week of January), ISO week number and day of week form a leap week calendar - instead of having 365 days in a common year and 366 in a leap year, it has 364 days in a common year and 371 in a leap week year, with leap weeks (obviously) being less frequent than leap days.
The Sym454 calendar [0] takes this idea further to create a perpetual calendar, with 12 months of 4 or 5 weeks; in leap years the 12th month is 5 weeks instead of 4 weeks long. However, the leap week rule proposed by Sym454 is different from that proposed by ISO 8601; the author of Sym454 argues his proposed rule has theoretical advantages (simple calculation and more uniform distribution of leap weeks). That said, there is a variant of Sym454 which uses the ISO 8601 leap week rule.
[0] https://kalendis.free.nf/symmetry.htm?i=1
> ISO 8601:2000 allowed truncation (by agreement), where leading components of a date or time are omitted. Notably, this allowed two-digit years to be used as well as the ambiguous formats YY-MM-DD and YYMMDD. This provision was removed in ISO 8601:2004.
(That's from https://en.wikipedia.org/wiki/ISO_8601 - I don't have the standards handy, ironically.)
Honestly I'm happy with either the RFC or ISO, but it seems like most normies haven't heard of RFCs so ISO is my default.
Totally insufficient for capturing important future events like the dead of the sun.
Conversion to UTC is not injective e.g. when clocks change or politics happen
No comments yet
My point is that this is an extremely niche case and works around one particular type of timezone insanity. You either have a team dedicated to dealing with timezone insanity, or you store stuff in UTC.
Either use dedicated "from_iso8601" functions, or manually specify the format of the input string ("%Y%m%dT%H%M%SZ")
But then discussion ensues about how programmers these days add libraries as dependencies for almost everything! :-)
I guess at some point a middle ground must be found.
But, then I guess we might need to account for fractured societies and actually store some kind of organizational code for which belief system the event author adheres to? :-)
Internally everything is stored and handled in TAI (better than UTC as no discontinuity) and translated from/to something else for human consumption.
I.e. for instance your should have logic to figure out what TAI period corresponds to "next month's meetings" if that's what the user wants, which you apply immediately on user inputs and then forget about DST, time zones, etc. in the rest of the code and storage.
Another benefit is that if your user was in New York but is now in London it is trivial and well-constrained to adjust to local time.
No comments yet
In Apple Calendar you can enable advanced timezone settings and you get a timezone override option.
No comments yet
UTC only loses information.
The problem is that can be difficult to portably determine. One wishes POSIX had an API “give me IANA time zone name for current process” which would do the needful to work it out (read TZ environment variable, readlink /etc/localtime, whatever else might be necessary)… but no, you are left to do those steps yourself. And it works reasonably well if the TZ environment variable is set, but it most commonly isn’t; readlink of /etc/localtime works on macOS and some Linux distros… but others make /etc/localtime a regular file not a symlink, which makes it all a lot harder
And that’s POSIX. Then there’s Windows which is possibly the last platform to still use its own timezone database instead of IANA’s. Now, Unicode CLDR maintains a Windows-to-IANA mapping table… but you have to ship both that table, and maybe the IANA timezone DB too, with your app, and keep them updated
I really wish Microsoft would ship the IANA database with Windows, and the IANA-Windows mapping table too, and provide APIs to query them, and keep them updated with Windows update. The core Windows OS and existing Windows apps can keep on using the legacy Windows TZ database for backward compatibility, whereas portable apps could use IANA instead if they wish
I think they have done exactly what you describe for several years at least:
https://learn.microsoft.com/en-us/dotnet/api/system.timezone...
You may argue that we can use local time to make the computations and be done with it, but during DST transitions, local time jumps so the number of actual seconds won't be consistent.
An engineer in the US reviewing industrial measurements logged in a plant in Asia from a variety of sources is definitely going to encounter lots of events recorded in local time. It would be maddening for that engineer to have to review and resolve events from different time coordinates, especially if they are doing the review months or years later. It's best to accept that reality and adopt local time as the standard. Then you must record the TZ offset per UTC in any new system you create.
edit: another commenter shared this link with an example: https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a...
I like their "Principle of preserving supplied data".
You are obfuscating it, for your own entertainment.
I use ISO for everything and your software wrongly assuming I want a deranged lunatic date format based on some locale is not going to cut it.
Locale is ok as a first guess, but maybe allow users tho make that choice?
I believe internationally that YMD and DMY are the two most common formats (and also the most logical), and the (much less logical) MDY comes third… YDM is a very distant fourth. MYD, DYM are theoretically possible but doubt anybody uses them
Actually, although MDY is by far most common in the US, I’ve seen US federal government forms that use DMY instead (although I imagine that’s rare, I’m sure you’ll find DMY US govt forms are greatly outnumbered by MDY ones)
I had never seen Y/D/M. I almost never see American use Day/Month order to begin with, let alone Y/D/M.
Year first and dashes is pretty much exclusively YYYY-MM-DD, no ambiguity; 2025-03-06 cannot be interpreted in any manner other than "the sixth day of the third month of the year 2025"
We'll use Y/M/D for systems or ordering, sometimes.
I can't recall having ever seen Y/D/M used in any notable sense.
I believe slashes are the most common separators in Japan (which uses that order), at least when explicit kanji for "year", "month" and "day" aren't used.
Special shoutouts to the author of node-postgres saying the PG's date type is better not used for dates in this case.[1] I love programming.
[1] https://node-postgres.com/features/types#date--timestamp--ti...
Is it sane? Is midnight at the start of a day, or the end of it? I'd think noon would be less ambiguous, and significantly less prone to these timezone issues (although this may not be a benefit).
Midnight at the start of the day: 00:00:00
Midnight at the end of the day: 24:00:00
Because the other languages & with bigger runtimes and more comprehensive standard libraries such as Java applets, Microsoft Silverlight, Macromedia Flash that were promoted for browsers to create "rich fat clients" were ultimately rejected for various reasons. The plugins had performance problems, security problems, browser crashes, etc.
Java applets was positioned by Sun & Netscape to be the "serious professional" language. Javascript was intended to be the "toy" language.
In 1999, Microsoft added XMLHttpRequest() to IE's Javascript engine to enable Outlook-for-web email that acted dynamically like Outlook-on-desktop without page refreshes. Other browsers copied that. (We described the early "web apps" with jargon such as "DHTML" DynamicHTML and "AJAX".) In 2004, Google further proved out Javascript capabilities for "rich interactive clients" with Gmail and Google Maps. Smoothly drag map tiles around and zooming in and out without Macromedia Flash. Even without any deliberate coordinated agenda, the industry collectively begins to turn Javascript from a toy language into the dominant language for all serious web apps. Javascript now had huge momentum. A language runtime being built into the browser without a standard library like Javascript was prioritized by the industry more than the other options like plugins that had a bigger "batteries included" library. This overwhelming industry preference for Javascript happened before Node.js for server-side apps in 2009 and before Steve Jobs supposedly killed Flash in 2010.
The situation today of Node.js devs using npm to download "leftpad()" and a hundred other dependencies to "fill in the gaps" of basic functionality comes from the history of Javascript's adoption.
Java's Date standard lib was awful for 2 decades, so there's no guarantee that a big standard library is a good standard library.
$ date
Thu 29 May 13:12:30 JST 2025
That is not a better world.
also this could've been handled easily by committee(ugh), or a 3rd party open source organization akin to linux foundation that just makes js library that all browser vendors use. Or making just a specification for JS handling things.
you know - like a lot of other languages are handled, including their standard library.
I mean, even Microsoft gave up and just went with Chromium, and they got the definition of almost infinite resources at their disposal.
Effectively if your website doesn't run in Chrome and Safari, it won't be seen by 99% of the market.
Ah yes, Microsoft, the defenders of the free world.
> Ah yes, Microsoft, the defenders of the free world.
No, Microsoft, one of the few businesses in the world that has both the technical ability, and the financial muscle, to be able to develop their own browser engine.
Who still chose not to. Leaving us stuck in the duopoly of Apple and Google, even outside of our mobile phones.
Extend
Enhance the world's beauty
Not a better world, just the current world.
[Ok that's enough, ed.]
What I'm looking for is "there has to be a library function for that; I would look it up".
JS was a compromise. It had to be sent out the door quick, it needed to look sufficiently like Java to not upset Sun who were trying to establish Java as the universal platform at the time while not being feature complete enough to be perceived as a competitor rather than a supplement. And it had to be standardized ASAP to pre-empt Microsoft's Embrace Extend Extinguish strategy (which was well on its way with JScript). That's also why it's an ECMA standard rather than ISO despite Netscape not having been based in Switzerland - ECMA simply offered the shortest timeline to publishing a standard.
I think what's more amazing isn't just how we managed to build the bulk of user interfaces in JavaScript but how we Node.js managed to succeed with ECMAScript 3. Node.js was born into a world without strict mode and without even built-in support for JSON: https://codelucky.com/javascript-es5/ - and yeah, ECMAScript 3 was succeeded by ECMAScript 5 not 4 because it took vendors 10 years to agree on how the language should evolve in the 21st century - not only did we build the modern web on JavaScript, we built a lot of the modern web on the version of JavaScript as it was in 1999! Even AJAX wasn't standardized until 2006 when Web 2.0 was already in full swing.
JavaScript even with all its thorns, it's a very consistent ecosystem nowadays, across browsers and architectures. Being forever retro-compatible is a good thing, meaning that most code that ran during the 2000s, can still be run with minimal change.
[1]: https://262.ecma-international.org/
[2]: https://www.w3.org/TR/
By that, I don't mean to dismiss the importance of backward compatibility, but this case is particularly funny because:
1. It had already been changed multiple times, each a breaking change, so it’s not like this form of compatibility was ever seriously respected;
2. Having it behave differently from other "legacy forms," like the slash-separated version, is itself arguably a break in backward compatibility;
3. As noted in the article, it never worked the same between Chrome and Firefox (at this point) anyway, so it’s doubtful how impactful this "breaking change" really was, considering you already had to write shim code either way.
console.log(new Date('2025/05/28').toDateString());
console.log(new Date('2025-05-28').toDateString());
console.log(new Date('2025-5-28').toDateString());
OutPut Below
Wed May 28 2025 debugger eval code:1:9 Wed May 28 2025 debugger eval code:2:9 Wed May 28 2025 debugger eval code:4:9
Falsehoods programmers believe about time gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b923ca
We swedes use standardized ISO 8601 dates such as YYYY-MM-DD as dictated by our excellent government and you find it in use in our social security number, government correspondence and mostly everywhere.
Same here in germany! ...Which is the reason why everyone ignores it in favour of the traditional format.
I love democracy, and also mountain-shaped temporal unit ordering ^ It's 28.05.2025 13:15.
Text-ordering by date is a nightmare because everything is first grouped by day-of-month, then month, then year! :)
- Understand the semantic difference between a timestamp (absolute time) and clock/calendar time (relative time). Understand which one your use case uses. Don't use one to store the other.
- If the use case calls for a relative time, do not manually construct or edit the date. Use your platforms date-creation/modification APIs, no matter how unnecessary they seem.
- Understand what is inside your platform's date types at rest. Understand which of your platform's date APIs pull in environmental information (time/tz/locale), as opposed to only using the arguments you pass it. Understand that your platform's 'print/stringify' function may be one of those aforementioned functions. Misunderstanding this often leads people to say inaccurate things. E.g. say your platform has a Date object that stores an epoch-based timestamp. People may say "the Date object is always in UTC", when really the Date object has no time offset, which is not the same thing.
- Understand that if you pass a date around platforms, it might accidentally be reserialized into the same absolute time, but a different relative time.
- Understand that there is a hierarchy of use cases, where each one has more complex requirements:
1. "Create/modify" timestamps; egg timers. (absolute time)
2. Alarm clocks (same clock time always).
3. One-time calendar events (has an explicit, static tz; same clock time if the user changes its day or time zone; different clock time if the user's time offset changes)
4. Recurring calendar events (same as above, except don't change the clock time if the user's time offset changed due to DST, as opposed to a geographic change)
5. Recurring calendar event with multiple participants (same as above, just remember that the attached tz is based on the creator, so the clock time will shift during DST for participants in a place without matching DST rules).
Note that a lot of platforms nowadays have built-in or 3rd party packages that automatically handle a lot of the rules in the above use cases.
Finally, understand that all those little weird things about dates (weird time zones, weird formatting conventions, legislative time zone changes, retroactive legislative time zone changes, leap days, leap seconds, times that don't exist), are good to know, but they will mostly be accounted for by the above understandings. You can get into them when you want to handle the real edge cases.
[1] https://www.destroyallsoftware.com/talks/wat
Being available everywhere (as far as browsers are concerned) trumps almost all other factors.
https://www.destroyallsoftware.com/talks/wat
[0]: https://xkcd.com/1179/
Just imagine building websites using literally any other language.
Sounds glorious, doesn't it?
The real "bug" in the example is 2025/05/28 being May 28th because the implementation ignores timezones for that format.
The issue with `Date` is that it is based on the original `java.util.Date` class and inherits all of its problems: https://docs.oracle.com/en/java/javase/21/docs/api/java.base... - this is also where the wonky zero-indexed month value comes from. Note that Java deprecated all versions of the constructor other than the one taking a millisecond value or nothing, which JS can't do for backwards compatibility reasons.
Hopefully `Temporal` will solve these problems but how long that spec has been in the works should tell you how difficult this is to get right when anything you put on the web is forever.
unless a timezone/offset is given, its considered plain date/time, not an epoch.