13 ms·
Never write your own date parsing library
- QuadmasterXLII 1y agoI ran into date heck recently in a medical setting for storing birthdates. Eventually I settled on the idea that a birthdate isn’t a physical time, it’s just a string. We can force the user to enter it in the format 02/18/1993 leading zeroes and all, and operations on it other than string equality are invalid. We’ll see if this survives contact with the enemy but it’s already going better than storing and reasoning about it as a point or interval in time and people’s birthdays changing when they move timezones.
- _mlbt 1y agoEven better, just make the user input dates using a calendar date picker widget instead of a text field. This gives you full control of the input.
- Tyr42 1y agoI've had to click back once per year old I am sometimes. I'd rather just type my birthday.
- mattkrause 1y agoI always find that a little annoying: it takes way too many clicks (esp. for a birth year) and then you've got to find the day of the week. I'd hate it less if typing updated the widget.
- kccqzy 1y ago> people’s birthdays changing when they move timezones That's because the developers use datetimes (aka timestamps) to store a single date. Just pick an arbitrary epoch date (such as January 1, 1900 as used by Excel, or my favorite January 1, 1600 since 1600 is a multiple of 400 making leap year calculations even simpler) and store the number of days elapsed since then. The rules involving leap years are much much simpler than rules involving timezones and timezone databases. The translation from/to this representation to a broken-down y/m/d takes only ~50 lines of code anyways. Of course if you don't need to do arithmetic on dates, just store three numbers, year, month, and day.
- happytoexplain 1y agoIn my humble opinion, this is not good advice unless you demonstrably need it for query performance or something. It is very easy for the logic layer to accidentally mess that up, either in reading or, worse, in writing back. In this case, I'd suggest storing what you mean (the user wasn't born 9,487 days after Jan 1 1970. They were born Dec 23, 1995.) Storing the literal units (and ONLY the relevant units), as the parent has, is robust and logically+semantically correct (they could add a translation layer for UX so the user doesn't have to be particular, but that's beside the point). Whether you use a string or a struct or some date-only type is moot, as long as you're literally storing the year, month, and day, and only those three things. You can ephemerally convert it to your platform's date type if you need to.
- SoftTalker 1y agoNo, don't do that. Use a date datatype (not date/time). You aren't the first person to ever need to handle dates without times/timezones in a computer program. Use what your database/language/libraries already have to support that.
- tadfisher 1y agoSpecifically, a "local date", codified as LocalDate in every date library worth a damn, except for Javascript which chose "PlainDate" just to be different.
- PaulHoule 1y agoWell, for hardcore chronology Julian dates are what you do. https://en.wikipedia.org/wiki/Julian_day https://en.wikipedia.org/wiki/Julian_day which are the moral equivalent of Unix timestamps with a different offset and multiplier. These work OK for human history but will break if you go far enough into the past or the future because uncertainty in the earth's rotation adds up over time. If you don't care about timezones timezones may still care about you, if you want to minimize trouble it makes sense to properly use timezone-aware Zulu (GMT) dates for everything if you can. In certain cases you might be doing data analysis or building an operational database for throttling access to an API or something and you know there are 16-bits worth of days, hours, 5-minute periods or something it can make sense to work relative to your own epoch.
- 8organicbits 1y ago> in the format 02/18/1993 Is this DD/MM/YYYY or MM/DD/YYYY? I can tell from the 18 that it's the latter, but that convention isn't universal. I'd recommend YYYY/MM/DD as a less ambiguous format, but I don't have a perfect answer.
- jack_pp 1y agoPretty sure they force the user into that format so that shouldn't be an issue
- kriops 1y agoFurthermore, require dashes over slashes to signal that you are expecting ISO-8601 compatible dates, i.e., YYYY-MM-DD. Most users does not know the standard even exists, but it serves as an affordance that it is different from dd/mm/yyyy, etc.
- PaulHoule 1y agoThose ISO-8601 dates are great for date processing with primitive tools such as GNU sort or awk since they sort lexically, at least if you're not comparing dates in different time zones.
- titzer 1y agoISO 8601 is the way.
- cyanydeez 1y agoalas, the user doesnt know the way...
- PaulHoule 1y agoThat part is easy. Use a date picker of some kind https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/date https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/... or a text field with some code that converts vernacular dates to a structured format. I don't think users are going to be too weirded out at seeing "1997-04-15" and will probably learn to use that natively. The hard part is that a lot of devs aren't aware that there's a standard and that standard is superior to the alternatives.
- PaulHoule 1y agoI guess in your case you're never doing date arithmetic or greater than or less than, but only doing equality testing, right? That is, it's part of a composite key. I faced a similar problem with a form where people were supposed to submit a date and probably not aware of what timezone was involved. I figured that so long as they selected "02/28/1993" and people always saw "02/28/1993" that was correct and if they ever saw it differently it was wrong. So I used non-TZ aware dates throughout the whole system.
- kaoD 1y agoI like how Temporal[0] does this. What you were dealing with is Temporal.PlainDate[1], i.e. a date with a calendar associated but no time or timezone (might be due to being implied but also might be irrelevant, like in birthdates). Temporal has other cool types, each with distinct semantics: - Instant: a fixed point in time with no calendar or location. Think e.g. "the user logged in at X date and time" but valid across the world for any timezone or calendar system. This is what we usually use "Unix UTC timestamps" for. - ZonedDateTime: like an Instant but associated with a particular calendar and location. Think an Instant but rendered "real" into a calendar system and timezone so the user can see a meaningful time for them. - PlainDate: already discussed. Think e.g. birthdates. - PlainTime: think "run task every day at 6:30pm". - PlainDateTime: like an Instant but associated with a calendar system, but no timezone. Think e.g. what a user would insert in a datetime picker, where the timezone is implied instead of explicitly selected. - PlainYearMonth: think e.g. "we'll run our reports during October 2025". - PlainMonthDay: think e.g. "my birthday is June 13". - Duration: think e.g. "the task ran for 3hrs 30min". Also see its important concepts[2]. [0] https://tc39.es/proposal-temporal/docs/ https://tc39.es/proposal-temporal/docs/ [1] https://tc39.es/proposal-temporal/docs/#Temporal-PlainDate https://tc39.es/proposal-temporal/docs/#Temporal-PlainDate [2] https://tc39.es/proposal-temporal/docs/timezone.html https://tc39.es/proposal-temporal/docs/timezone.html
- keeganpoppen 1y agoyeah, it was a long (and painful) time coming, but i think the temporal api finally basically nailed it. you know a library is good when you learn something about how to think about the problem just from how the code/api is structured.
- benreesman 1y agoRelatedly, std::chrono isnt exactly a beauty, but it did get people thinking about time points and durations and clocks and which operations are valid ways to move among them. Stuff like this is good.
- Terr_ 1y agoI hope that as time goes on software design get better about modeling things that are guesses, conjecture, etc. rather than Absolute Facts. As-is, we assume lots of things are facts and we just hope it's true enough to avoid problems. (Starting with the business requirements. :p )
- dragonwriter 1y agoWhat environment are you in where you have to work with birthdates, you have timezone aware dates, times, and intervals, but you don't have a naive/plain/local date type that already exists forcing you to use strings in place of date-without-timezone? You seem to have a reasonably expedient solution for that problem, but it is surprising to have the combination of things you have to have and things you have to be missing to have that problem in the first place.
- happytoexplain 1y agoThey may have something that's just not as easy to work with as strings. E.g. in Swift, you have DateComponents, but that's too dynamic (and Date is sometimes referred to as naive, but that's a misunderstanding, since they are timestamps, not date+time).
- QuadmasterXLII 1y agoJavascript/swift/kotlin frontend, python backend, mysql server. The problem wasn’t that I had access to zero (presumably) well implemented time abstractions with all the bells and whistles, it was that I had five well implemented native time abstractions.
- BurningFrog 1y agoNormal/"legal" dates are not timestamps or related to timezones, and this fact will eternally be rediscovered as long as humans write software.
- shadowgovt 1y agoIIUC why medical cares at all, this is really insightful. Because as far as I'm aware, the medical industry basically uses birthdate as a key; it helps to (a) tell two patients with other primary keys (like name or address) apart and (b) do a quick mental-acuity check on the patient by just having them regurgitate the value and doing a human-brain string= on it.
- 1718627440 1y agoThe dose varies per age, but this isn't that exact.
- legulere 1y agoIf you store it just as a string it means that you cannot do anything useful with it like age-dependent logic or you just pass on parsing logic to users of the field. FHIR in my opinion has a pretty good system for dates (including birthdates): YYYY, YYYY-MM, or YYYY-MM-DD. (Not knowing your exact birthday is common for some countries). https://build.fhir.org/datatypes.html#date https://build.fhir.org/datatypes.html#date
- danesparza 1y agoI mean. Yes. Don't write your own date parsing library. Unless you want to go nuts. https://gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b923ca https://gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b...
- micromacrofoot 1y agoMultiple times in my career I've had a good laugh when a non-technical manager says something along the lines of "it's just the date, how hard can it be?"
- indymike 1y agoAdd phone numbers, email addresses and human names to the list.
- econ 1y agoJust validate the registration form? Surely this is a solved problem? Uhhh...
- micromacrofoot 1y agoWhat do you mean we shouldn't have a first and last name input? explains the naming conventions of every culture on the planet
- bigstrat2003 1y agoWhich is not relevant unless you are trying to support every culture on the planet. Which most people aren't, and for them it'll be just fine to have first+last name.
- micromacrofoot 1y agoYou'd be surprised how often two fields mess up names if you live in a place that has any amount of immigration.
- peheje 1y agoAgreed! My team is constantly humbled by the mess of user data: names, birthdays, addresses, people dying or living abroad etc. Honestly, sometimes I think about the linear algebra, AI, or robotics I learned in school and get this feeling of, "Is this what I'm doing? Stuff that feels like it should be simple?" It's funny, even our product manager - who is a great guy - can fall into that "come on, this should be easy" mode, and I'll admit I sometimes get lulled into it too. But to his credit, every time I walk him through the actual edge cases, he totally gets it and admits it's easy to forget the on-the-ground complexity when you're in 'planning mode'. So yeah, seeing your comment is incredibly validating.
- deleted 1y ago[deleted]
- davidw 1y agoIt's like that joke someone posted on Twitter: "I was in favor of space exploration until I realized what it would mean for date/time libraries"
- TheJoeMan 1y agoIt's funny to reason why we must go to bed when the clock has a certain number, since modern technology could easily be programmed to adjust as needed. No technical reasons the Martians can't go to bed at 9:00am today and 9:40am tomorrow. This mirrors my thoughts on why farmers caring about daylight savings time is farcical, farmers I know use the timekeeping of "crack of dawn" and "sunset".
- Arainach 1y agoPeople want to understand when things are open/reasonable without having to do a lookup every time. A conversion has to happen somewhere - either I can say "X is in timezone foo. It's 1300 there so they're awake and I can call them" or "It's 1900 UTC, X is awake from....err....2200 to 1400, so I can call now". The first is significantly easier as it requires remembering only a single offset and then going with societal conventions.
- msla 1y ago> "It's 1900 UTC, X is awake from....err....2200 to 1400, so I can call now" Assuming it's that simple of course. Like, you can do mental math about what UTC "officially means" for someone many miles away, but people coordinate with others even if it means their local schedule is not aligned with that ideal case. Time zones account for this by being wider or narrower than their Platonic 15° of longitude ideal in some places.
- dmoy 1y agoiirc DST was never about farmers, and always about energy usage (lighting, etc) in the evening Agree I've never met a farmer who cares about DST. Though also, for non-ag farmers, sometimes "crack of dawn" isn't early enough lol. Cow: "Dairy barn has electric lights, why aren't you awake at 4am tending to my needs, Human? Vacation? Lol no, stay here. Every morning. 4am."
- the__alchemist 1y agoGood general rule of thumb, but desperate scenarios call for desperate measures. I would never do this in Python or Rust for example, but it's necessary in Javascript; `Date` and `Moment`, are so full of traps that the ends justify the means: Especially if you have use for a `Date` or `Time` type.
- deleted 1y ago[deleted]
- jimmaswell 1y agomoment's given me no trouble at all. I certainly haven't found it to be full of traps. Addressing the most common complaint: a moment object is mutable, sure - that's a valid design choice, not a trap. Follow the docs and everything works perfectly well IME.
- the__alchemist 1y agoAs a specific point, I have not safe found a way to represent a date or time in Moment. When I point this out, I generally get agreement from people who are more used to other languages, and the claim that "You should never be representing a date or time; everything should be a datetime" by JS devs.
- thangalin 1y agoOn a slightly related note, here's an algorithm for parsing time from natural inputs into a normalized time: https://stackoverflow.com/a/49185071/59087 https://stackoverflow.com/a/49185071/59087
- jimmaswell 1y agomoment is far smaller if you include it without locales you don't need. I don't care how much they talk themselves down on their homepage, begging me to choose a different library - I like it and I'll continue using it. > We now generally consider Moment to be a legacy project in maintenance mode. It is not dead, but it is indeed done. > We will not be adding new features or capabilities. > We will not be changing Moment's API to be immutable. > We will not be addressing tree shaking or bundle size issues. > We will not be making any major changes (no version 3). > We may choose to not fix bugs or behavioral quirks, especially if they are long-standing known issues. I consider this a strength, not a weakness. I love a library that's "done" so I can just learn it once and not deal with frivolous breaking changes later. Extra bonus that they plan to continue making appropriate maintenance: > We will address critical security concerns as they arise. > We will release data updates for Moment-Timezone following IANA time zone database releases.
- TheBigSalad 1y agoI couldn't agree more. I have no idea why the moment devs are trying to kill moment.
- FigurativeVoid 1y agoI used to work at a company that stored all dates as ints in a YYYYMMDD format. When I asked why, I was told it was so we could subtract 2 dates to get the difference. I asked them why they couldn’t use DATEDIFF since this was in a sql db. They said they hadn’t heard of it and that it must be new.
- dguest 1y agoWait so one day over the new year is 2025-01-01 - 2024-12-31 = 20250101 - 20241231 = 8870 i.e. 90 months and 10 days or 7 years 6 months and 10 days How is that the same thing as one day?
- cortesoft 1y agoIt is even worse than that, each month boundary breaks it, too: 2025-02-01 - 2025-01-31 = 20250201 - 20250131 = 70
- rootsu 1y agoThey might be subtracting taking first 4 digits and the subtracing yyyy-yyyy, mm-mm and dd-dd.
- dguest 1y agoWhich sort of works, but then you also have to deal with the cases where the days or months go negative (at the month and year bounds), and that also involves knowing how many days there are in each month. It's pretty difficult for me to imagine how this could be easier than just converting to e.g. unix time and subtracting seconds.
- FigurativeVoid 1y agoOh it never worked. It was bad design by someone who was well meaning, but inexperienced. All these issues were resolved, usually, by parsing the date into a proper Date class.
- jabroni_salad 1y ago
- wood_spirit 1y agoYeah don’t do it! But subtle plug of something I made long ago for when you find your data pipelines are running hot parsing timestamp strings etc: https://github.com/williame/TimeMillis https://github.com/williame/TimeMillis I’m still pumped by the performance of the thing! :)
- bob1029 1y agoI like to use the Japanese calendar as an example to scare the juniors away from DIY parsing: https://learn.microsoft.com/en-us/dotnet/api/system.globalization.japanesecalendar?view=net-9.0 https://learn.microsoft.com/en-us/dotnet/api/system.globaliz... https://learn.microsoft.com/en-us/windows/apps/design/globalizing/japanese-era-change https://learn.microsoft.com/en-us/windows/apps/design/global...
- colesantiago 1y agoI don’t see anything wrong with this. This is actually a fun challenge. I encourage everyone to learn how to parse the japanese calendar format. The more people know the better!
- kccqzy 1y agoDo your users type in such dates? No? Problem solved. The benefit of DIY parsing is to make the problem simple by restricting it to the set of plausible inputs your users will want your code to handle, not to make a highly general library. The right takeaway for juniors is to stop over-complicating things.
- bigstrat2003 1y ago> Do your users type in such dates? No? Problem solved. This is spot on. So many of the "X is really hard and your intuition is wrong" takes ignore the fact that most people are not building something which needs to be usable in every country, language, and culture on this earth. Yes, human behavior is insanely complex, but for any given application you can probably ignore huge swathes of it.
- its-summertime 1y agoI put these into an ISO8601 parser and it didn't work, I'm going to tell ISO off for obviously DIYing their solution instead of doing the proper thing.
- jedberg 1y agoThings you should never do: Make your own load balancer software Make firewall software Make a date parsing library Attempt to verify an email with a regular expression.
- 9rx 1y agoRoll your own encryption Accept people's names Anything
- the__alchemist 1y agoIs parsing HTML with regexes Ok?
- dimaaan 1y agoNo. See https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags https://stackoverflow.com/questions/1732348/regex-match-open...
- 9dev 1y ago> Attempt to verify an email with a regular expression. .+@.+ That one always seemed sufficient for me, every issue after that is the users problem
- jedberg 1y agoObviously there is a bit of nuance here, but the best rule of thumb is use a regex and then warn the user that it doesn't look valid but still accept it if it doesn't pass, and then send an email to verify it.
- deleted 1y ago[deleted]
- 1718627440 1y agoExcept email addresses don't need to have an "@".
- fitsumbelay 1y agobefore I even read the post lemme just say "too late, friend. faaaaar too late ..."
- senfiaj 1y agoIn UIs prefer date/time pickers instead of raw text inputs which will give the date/time in standard ISO format such as ("2025-07-25" or "2025-07-25T18:47:26.022Z"). Prefer ISO formats everywhere where possible.
- somat 1y agoThe thing that bothers me about the firefox date picker is it display the date in YYYY/DD/MM format. While I am fairly sure this a a locale defined thing. locales are this huge pile of worms and I have never figured out how to change it to show YYYY-MM-DD format
- senfiaj 1y agoAt least the real input value is in YYYY-MM-DD. Also the date picker will show the day in it's calendar UI.
- x187463 1y agoRelevant Computerphile: https://www.youtube.com/watch?v=-5wpm-gesOY https://www.youtube.com/watch?v=-5wpm-gesOY
- CurtHagenlocher 1y agoIn 2009 I made a note that Excel's main date parsing function was over 1000 lines of code -- not including helpers.
- takinola 1y agoNo other programming concept has caused me more grief than dealing with time and timezones. It starts to get really mind-bendingly complex once you start thinking about it deeply. That is even before you start encountering the quirks (some places have timezone changes that depend not only on the time of year but also on the actual year). Lesson learnt - choose a library (moment is great) and never think about time again.
- whatever1 1y agoIt’s because it is not systematic historically. It’s a system full of edge cases
- hnuser123456 1y agoIt's also a beautiful maze of nerd snipes. There's apparently some shifting going on inside the earth, combining with the slight variability of the moon's distance, which means various days over a month can be more than a millisecond shorter than average. Good luck integrating that into your date.addDays()
- SAI_Peregrinus 1y agoThe more precisely you try to measure anything the more confounding factors you encounter. Take length as an example: every material has some coefficient of thermal expansion, and that coefficient can itself change with temperature. Even Zerodur. Every material has a finite speed of sound. If you measure length precisely enough and fast enough, you'll find every material changes length as ambient sounds pass through. So everything is a thermometer, and a microphone, and more since there are many other "parasitic" variables.
- cbm-vic-20 1y agoUnfortunately, not many people in our industry really understand the common pitfalls of timezone management, including the people who set the requirements. The classic "I want this to run at 2am each weekday for the user", and then proceed to simply store that as a UTC offset and call it a day (pun intended).
- quelsolaar 1y agoWhen ever i see "never implement your own...", i know i want to implement it myself. People say that about hard things, and I only want to do hard things. Nobody wants people who can do easy things, people want people who can do hard things. The only way to learn how to do hard things, is to do hard things, so do the hardest things. So go ahead, write your own date library, your own Unicode font rendering, compiler, OS, game engine or what ever else people tell you to never do because its hard.
- fsckboy 1y agoyou want to do something people really think is hard? use C. it's not safe. all the people who say C is not safe have downvoted me for quoting them
- quelsolaar 1y agoI exclusively write in C89. I'm a member of the ISO C standard board.
- boothby 1y agoThe confluence of tinker-for-tinkerings'-sake "hackers" and get-rich-quick "hackers" on this site certainly leads to a lot of fun miscommunication.
- glibby 1y agoBy all means, write it. Just don't use it. These warnings are almost always in the context of code you're going to release, not exercises in learning on your own.
- ramijames 1y agoThis is such nonsense. All the stuff that we use, someone wrote. If nobody makes them, then how is that going to work? The messaging here is that you should be careful about using what you build on your own because it: - hasn't been battle tested - likely has bugs - isn't mature The only way that it will be all of those things is if someone invests time and energy in them. From an ecosystem perspective this is absolutely the right thing. You want duplicate projects. You want choice. You want critical knowledge to be spread around.
- deleted 1y ago[deleted]
- aaroninsf 1y agoFunny, I wrote my own, so had to click, but mine was for a very different use case: converting extremely varied date strings into date ranges, where a significant % of cases are large number are human-entered human-readable date and date range specifiers, as used in periodicals and other material dating back a century or two. I.e. I had correctly interpret not just ISO dates, but, ambiguous dates and date ranges as accepted in (library catalog) MARC records, which allows uncertain dates such as "[19--]" and "19??", and, natural language descriptors such such as "Winter/Spring 1917" and "Third Quarter '43" and "Easter 2001." In as many languages as possible for the corpus being digitized. Output was a date range, where precision was converted into range. I'd like to someday enhance things to formalize the distinction between ambiguity and precision, but, that's a someday. When schema is totally uncontrolled, many cases are ambiguous without other context (e.g. XX-ZZ-YYYY could be month-day-year or day-month-year for a large overlap); and some require fun heuristics (looking up Easter in a given year... but did they mean orthodox or...) and arbitrary standards (when do seasons start? what if a publication is from the southern hemisphere?) and policies for illegal dates (Feburary 29 on non-leap-years being a surprisingly common value)... In a dull moment I should clean up the project (in Python) and package it for general use...
- neilv 1y agoThis article doesn't get into some of the special fun of ISO 8601, including relative values, non-Gregorian values, durations... Some of the things in the standard are surprising, like maybe were a special request. At the time, I commented, something like, Somewhere, in the French countryside, there is a person who runs an old family vineyard, that is still stamping their barrels with the timepoint information [...]. And that person's lover was on the ISO 8601 committee. (I once wrote an time library in Scheme that supported everything in ISO 8601. It did parsing, representation, printing, calendar conversion, and arithmetic. Including arithmetic for mixed precision and for relative values. It was an exercise in really solving the problem the first time, for a core library, rather than cascading kludges and API breakage later. I don't recall offhand whether I tried to implement arithmetic between different calendar systems, without converting them to the same system.)
- MathMonkeyMan 1y agoI'd be interested in seeing the Scheme code if it's open source!
- endoblast 1y agoI'm not even a programmer, but I can tell that dates are ambiguous a lot of the time. e.g. dd/mm/yyyy (British) and mm/dd/yyyy (USA) can be confused for the first twelve days of every month. So, given the high volume of international communication, I think we should hand-write months in full, or at least as the first three letters (Jan, Feb, Mar, ..., Dec) We should also abandon three-letter acronyms (but that's another story).
- macintux 1y agoI wrote one in Erlang years ago for Riak’s time series implementation. I don’t remember all of the motivations, but most of all I wanted the ability to encode incomplete date/time objects. https://github.com/macintux/jam https://github.com/macintux/jam I’d like to get back to it. If nothing else, I dearly miss using Erlang.
- champtar 1y agoI once had to maintain a CalDAV server that was developed in house, computing the "free busy" with recurring events, exceptions, different timezone than the organizer + some DST is a bug source that keeps on giving.
- fHr 1y agofucking daylight saving time I had to fix a few weeks ago on the change back on last Sunday October where the same hour occurs twice .
- Hizonner 1y agoNever mess with cryptography, times, Unicode, or floating point.
- deleted 1y ago[deleted]
- deadbabe 1y agoOf course I won’t write my own, AI will just write it for me.
- ayaros 1y agoI will now post the relevant Tom Scott video: https://www.youtube.com/watch?v=-5wpm-gesOY https://www.youtube.com/watch?v=-5wpm-gesOY I tried it. I will never try again unless I take, like, six months to plan out how the system will work before I even write a single line of code.
- deepsun 1y agoNothing came close in quality to Joda-time from Java (later adopted with small fixes as "java.time" built-in). Why not using js-joda port?
- yas_hmaheshwari 1y agoI never knew that js-joda existed. I love Joda library. Its surprising that date / time parsing is screwed in multiple languages
- spankalee 1y agoAs for this aside: > As an aside, this search has made me tempted to ask: do we need to keep Dual publishing packages? I prefer ESM over CJS but maybe just pick one? Pick ESM. CJS doesn't work in browsers without being transformed to something else. Node can require(esm) now, so it's time to ditch CJS completely.
- userbinator 1y agoYou're right, you should never need a library but just a "sscanf("%04d-%02d-%02d..." ;-) IMHO needing to handle multiple, possibly obscure, date formats simultaneously is nearly never a problem in practice.
- vivzkestrel 1y agowhat is your issue with dayjs?
- danneezhao 1y agoGreat writeup! Your journey perfectly captures the universal developer dilemma: "Never roll your own X... until you absolutely must." The bundle size reductions are impressive (230kB client-side savings!), and your RFC 9557 alignment is a smart forward-looking move. Two questions: Edge cases: How does your parser handle leap seconds or pre-1582 Julian dates? (e.g., astronomical data) Temporal readiness: Will @11ty/parse-date-strings become a temporary polyfill until Temporal API stabilizes, or a long-term solution? Minor observation: Your comparison table shows Luxon supports YYYY-MM-DD HH (space separator) while RFC 9557 doesn’t – this might break existing Eleventy setups using space-delimited dates. Maybe worth an explicit migration note? Regardless, fantastic work balancing pragmatism and standards. The web needs more focused libraries like this!
- xingwu 1y agoThank you for sharing. I like such subtle branding. I will try 11ty when I need a static site generator. All engineers please follow this example when you want to promote your product, even when you don't want to promote your product.
- fsckboy 1y ago>Consider "200". Is this the year 200? Is this the 200th day of the current year? Surprise, in ISO 8601 it’s neither — it’s a decade, spanning from the year 2000 to the year 2010. And "20" is the century from the year 2000 to the year 2100. there is so much wrong with this paragraph, it's a nest of people who shouldn't work on date parsing. there is no way 200 is any kind of date, but if you're going to insist it is, 2000 to 2010 is 11 years unless "to" means "up to but not including" in which case it should say 2001 to 2011 if you want to refer to the 200th decade, since decade 1 was 1AD through 10AD... there is no saving this post
- tobyhinloopen 1y agoI agree, "200" is just "NotADate". I like JS-Joda's date formatting.
- eterm 1y ago> 2000 to 2010 is 11 years This is obviously wrong by induction. If 2000 to 2010 is 11 years, then: 2000 to 2009 would be length 10 years ... 2000 to 2001 would have length 2 years and finally 2000 to 2000 would be a span lasting "1 year". But any span with the same start and end point must have length zero, it's nonsensical to have a system without that property. As for the spec, ISO 8601 defines a decade as a period of 10 years starting with a year divisible by 10 without a remainder. Decade 1 is year(s) 10 through 19.
- fsckboy 1y ago>any span with the same start and end point must have length zero "a year" is not a point, it's a span. so is a decade. >Decade 1 is year(s) 10 through 19 but the property you are trying to describe goes hand in hand with 0-based indexing, and thus we see that ISO Decade 0 is >sad tuba< 9 years long
- eterm 1y agoIt is actually 10 years long by how ISO 8601 defines a decade. Also it's worth noting here that ISO 8601 has a year zero, which equates to 1BC in historical terms.
- ozgrakkurt 1y agoMaybe the title should be “it is difficult to write a date parsing library” “Never write your own x” kind of titles come off as arrogant and demotivating. Maybe some other person will write an excellent date parsing library that will be better than current ones? Maybe they think it is worth to spend some time on it? These kinds of hard things tend to have libraries that are extremely bloated because everyone uses one library, and that one library has to work for everyone’s use case. You can see this in the post too, not everyone needs to be able to parse every single date format.
- dylan604 1y agoI'll stand by the never roll your own crypto, but never roll your own date parsing library that your DIY crypto library depends would be uber scary
- aussieguy1234 1y agoAlmost never... There may be some obscure cases. Like for example, lets say you are writing very performance sensitive code where nanoseconds count. All of the date parsing libraries available for the language you are writing are too slow for your requirements. So you might roll your own lighter weight faster one.
- Animats 1y agoI requested an ISO 8601 date parser in the Python "datetime" library in 2012.[1] "datetime" could format into ISO 8601, but not parse strings. There were five ISO 8601 parsers available, all bad. After six years of bikeshedding, it was was fixed in 2018. That's what it took to not write my own date parsing library. [1] https://github.com/python/cpython/issues/60077 https://github.com/python/cpython/issues/60077
- motorest 1y ago> That's what it took to not write my own date parsing library. If you wrote your own date parsing library, there would be six ISO 8601 parsers available, all bad. You should feel grateful for not having wasted your time.
- xaer 1y agoI wrote the ethlo ITU library because I was annoyed with the lack of performance and large amount of ceremony to parse and format standard timestamps in RFC-3339 format in Java. It is somewhat more extensive now, and is used in other libraries. Ask me anything!
- bryanrasmussen 1y agoso, anyway, never do this which I did and have great technical reasons why it had to be done for my language and needs.
- jillesvangurp 1y agoIMHO, ISO 8601 as a standard is way too broad and unspecific. ISO 8601 is way too messy. Telling somebody that they need to parse an ISO 8601 date time is not enough information to do the job. Which variant is it? Does it include the time part. IMHO allowing the full range of ISO 8601 dates and times in a data format is usually a mistake. You want to be more specific. There's a need for a standard that locks down the commonly used variants of it and gets rid of all the ambiguity. For me, timestamps following this pattern 'YYYY-MM-DDThh:mm:ss.xxxxxZ' is all that I use and all my APIs will accept/produce. It's nice that other legacy systems are available that don't normalize their timestamps to UTC for whatever reason, that consider seconds and fractions of a second optional, etc. But for unambiguous timestamps, all I want is this. It's fairly easy to write a parser for it. A simple regular expression will do the job. Of course add unit tests. Technically the Z is redundant information if we can all agree to normalize to UTC. Which IMHO we should. In the same way the T part and separators are redundant too. But they are nice for human readability. You can use datetime libraries that are widely available to localize timestamps as needed in whatever way is required locally. But timestamps should get stored and transmitted in a normalized and 100% unambiguous way. It's only when you get into supporting all the pointless and highly ambiguous but valid variants of ISO 8601 that parsing becomes a problem. There's actually no such thing as a parser that can parse all valid variants with no knowledge of which variant is being used. There are lots of libraries with complex APIs that support some or all of the major and minor variants of course. But not with just one function called parse(). I think the main challenge with ISO 8601 is that it never called out this variant as a separate thing that you should be using. This really should be its own standard. And not using that would be a mistake. ISO 8601 is what happens when you do design by committee.
- ttiurani 1y ago> You can use datetime libraries that are widely available to localize timestamps as needed in whatever way is required locally. But timestamps should get stored and transmitted in a normalized and 100% unambiguous way. If by "timestamp" you mean past dates and deterministic future dates, then agreed. (Although I prefer unix epoch in ms for those, to be able to use integers and skip string parsing steps completely.) But if your unlucky enough to need to handle future dates, especially "clock on the wall" ("let's meet in Frankfurt on July 26th 2029 at 1pm"), then you just can't know the timezone. The reasons can be many political ones, but especially in this case there's a high probability that EU will remove daylight saving time by then. So in those cases, if you want to be correct, you'd need to include the geolocation in the stored timestamp.
- bdhcuidbebe 1y agoNever say never
- cultureulterior 1y agoPity they're dropping week number- it's used so much in Europe.
- ashoeafoot 1y agoNow i want to make a date format, combined with other data that is the ultimate challenger of date parsing. IntroDuceThing: The ip:port,date/time,longlat string. Oh, yes its format is also dependant on the language you encode it in and what parts you leave out to be defaulted. .:, is now a valid locationdateip
- atoav 1y agoWell, I did that. And it works flawlessly for a decade now. The thing is just that I know and control the context from which the dates are being parsed. If you're now like: "Yeah ok if you're the one who sends the data being parsed it might be okay", the claim of "never do X" is proven wrong if there are specific situations where soing X is not only okay, but might be the sensible option. Which is why you should never use the word "never" unless you're really sure you can't come up with a situation that is an exception.
- stevage 1y agoThey didn't say whether it would have been feasible to just extract that one function from the library - sort of manually tree-shaking, if you will.
- zelphirkalt 1y agoThe table of listed date formats doesn't look too difficult to implement. A quick look at the RFC tells me, that the RFC even specifies a grammar, though very incomplete. It would be prudent to specify a complete grammar in the RFC of course. Then it would be even simpler taking that grammar and translating it to whatever library one uses for describing grammars for parsing stuff. I really hope all these libraries didn't make silly things with regexes ...
- aidenn0 1y ago> ... billed as “an extension to the ISO 8601 / RFC 3339” formats The quote comes from MDN[1], but is wrong on so many levels: 1. RFC 3339 is not a format; it is a meta-format. It specifies properties that any timestring used in internet applications should have. One application could require that "T" be used to separate the date and the time, while another could require a space to be used, and both applications would conform to 3339. Using the same parser to parse times and dates from the two applications would be incorrect, as "1234-12-12 12:34 ..." unambiguously represents the date of December 12, 1234 in the former but the time of 12:34 on the same day in the latter. 2. RFC 3339 is thus not a subset of ISO-8601; there exists a subset of ISO-8601 which satisfies RFC 3339, but there also exist many timestrings that are not subsets of ISO-8601 which also satisfy it (most famously replacing "T" with a space, but that is merely an example for which RFC 3339 conforming applications may deviate from the ABNF in the RFC for readability). 3. It is obvious from both #2 and the table in TFA that RFC 9557 can't be an extension of ISO-8601 given that there are valid ISO-8601 timestrings in the table that are invalid RFC 9557 timestrings. 4. This is a minor nitpick, bu RFC 9557 also alters the semantics of some RFC 3339 timestrings with regards to offsets. RFC 3339 specified "Z" (or "z") for the offset being the same as +00:00, while 9557 has "Z" being the same as -00:00; the meat of RFC 9557 is adding suffix-tags to RFC 3339, so I wouldn't quibble with calling 9557 an extension of 3339. 1: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant#rfc_9557_format https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- dbg31415 1y agoRelevant. https://m.youtube.com/watch?v=-5wpm-gesOY https://m.youtube.com/watch?v=-5wpm-gesOY
- cobertos 1y ago> Most date parsing woes (in my opinion) come from ambiguity: from supporting too many formats or attempting maximum flexibility in parsing. ... There is a maintenance freedom and simplicity in strict parsing requirements ... Is this the endgame of "be liberal in what you accept, but strict in what you output"? You end up supporting an untold amount of usage patterns, not even chosen by yourself if you use a library like `luxon` to handle the "be liberal" part for you.
- MichaelRo 1y ago>> I made the very sensible choice to adopt luxon as the Date Parsing library for Eleventy. Never heard of neither Luxon nor Eleventy but by the ridiculous gay names only I could have bet a million dollars this is yet another instance of the insanity that's Javascript. Honestly, noone outside of the sickening dysfunctional Javascript ecosystem does that, keep rewriting basic crap ad infinitum.
- pavel_lishin 1y ago> Consider "200". Is this the year 200? Is this the 200th day of the current year? Surprise, in ISO 8601 it’s neither — it’s a decade, spanning from the year 2000 to the year 2010. And "20" is the century from the year 2000 to the year 2100. In any sane system, giving a function "200" as an input and asking what date/datetime it represents should return some sort of error. Some inputs are too ambiguous to meaningfully parse.