[HN Gopher] Is It Time for the JavaScript Temporal API?
       ___________________________________________________________________
        
       Is It Time for the JavaScript Temporal API?
        
       Author : ceeb
       Score  : 133 points
       Date   : 2021-12-28 09:57 UTC (2 days ago)
        
 (HTM) web link (blog.openreplay.com)
 (TXT) w3m dump (blog.openreplay.com)
        
       | toomanybeersies wrote:
       | I'm happy to see that it includes primitives of varying
       | precision, specifically, that it includes PlainDate [1], which
       | represents a calendar date, with no timezone. This year, I've
       | spent far too many days, probably weeks, fixing tedious bugs due
       | to incorrect handling and parsing/formatting/reparsing of dates.
       | 
       | [1] https://tc39.es/proposal-temporal/docs/plaindate.html
        
       | rco8786 wrote:
       | > 74Kb payload
       | 
       | Is 74Kb really a cause for concern on modern internet
       | connections? I realize death by 1,000 cuts, etc...but for such a
       | core set of functionality that seems pretty reasonable.
       | 
       | DayJs is 2 (two) Kb. Perfectly reasonable for any app with
       | minimal date handling needs.
       | 
       | (BTW I'm 100% in support of a native temporal API also, although
       | have some gripes with the Dev Exp of what's shown in this post)
        
         | mkotowski wrote:
         | From my personal experience in Poland:
         | 
         | You can have LTE+ or even 5G in cities, but traveling by train
         | means that in some areas only a select few extra-lightweight
         | pages like Hacker News are able to load before a timeout or
         | connection loss occurs.
         | 
         | So yes, in some situations even that amount of payload could
         | have a meaningful impact.
         | 
         | "Modern" connections are irrelevant if we are talking about
         | regions, which are not viable for a high-speed infrastructure.
         | And such places are almost everywhere. Mountainous parts of
         | Japan, many American regions, or sparsely populated Polish
         | regions.
         | 
         | Of course, how much it is important varies greatly.
        
         | onion2k wrote:
         | _Is 74Kb really a cause for concern on modern internet
         | connections?_
         | 
         | That depends on how you define what a modern Internet
         | connection is. If you mean a fast, low latency, unmetered
         | connection then 74kb is obviously fine.
         | 
         | If you mean a 4G connection on a train, or a metered rural
         | satellite connection, or a typically-low-income-user pay-for-
         | data connection, or even a fast cheap Internet connection but
         | with a low-end device that will waste a lot of battery power
         | parsing and running all that JS code, then it's a lot less
         | obvious.
         | 
         | Most of the time you don't know who the user is, so it's best
         | to assume the worst case. If your site works well when things
         | aren't ideal then it'll be awesome when they are good too. Only
         | thinking about the happy path of users with M1 Macbooks with
         | unlimited gigabit ethernet will mean everyone else has a sucky
         | time on your site.
         | 
         | Also, if someone posts your site on HN, most of the comments
         | will be about how bad the code is and you'll miss out on
         | feedback that's actually useful. If you're deploying a 74kb
         | date library, think of your karma.
        
         | jacobr wrote:
         | It's also 74 additional kb to parse and evaluate on the main
         | thread before it can continue doing more interesting things
         | like rendering the main content you came to the page for. On
         | many devices (a huge number of users globally are on dirt cheap
         | underpowered phones) this adds up to significant user
         | experience problems.
        
         | tofflos wrote:
         | I see it more as issues with fragmentation, wasted effort, and
         | security. An anemic standard library forces every developer to
         | either evaluate, or author, an alternative. This leads to an
         | explosion of alternatives, which in turn makes it harder to
         | agree on best practices and harder to secure the software
         | supply chain.
        
         | enumjorge wrote:
         | There are a lot of places in the world and even the US where
         | people have slow connections. It's also not just download speed
         | that's the problem. Slower phones need to process all that JS.
         | 
         | I'd say that time-related API being core functionality makes it
         | more of a reason why this should be baked into the standard JS
         | API. Why make users download something that most sites and web
         | apps use?
        
         | nobleach wrote:
         | My take: ABSOLUTELY! 74kb or image data? Probably not. But
         | unzipping, parsing/JITting/running/whatever that large of a
         | payload.... on crappy 3 year old low-memory Android devices...
         | yes. That is going to lag.
         | 
         | Not too long ago, Google tried to push AMP on all of us because
         | devs were getting way too careless with their bundle sizes.
         | We're still not to a decent place just yet. Internet speeds in
         | The United States, Europe and populated Asia may be growing but
         | there's an entire world that are still at "slow-3G" speeds.
        
         | jazzyjackson wrote:
         | Even in locales with high speed internet, I find myself sharing
         | a wifi router with a dozen or more devices in classrooms or
         | coffee shops. It is a bit disheartening seeing google docs and
         | slack struggle to stay responsive, and in a college town with
         | fiber internet. I've also tried collaborating on satellite
         | internet on a farm and at the end of a microwave-tower-daisy-
         | chain, where youtube works great if you're the only one in town
         | using the connection.
         | 
         | I think people assume Starlink will bring high-speed internet
         | to every corner of the globe, but that being the case, there's
         | more situations where groups of people will share a single
         | downlink, and still every kilobyte counts.
        
         | moksly wrote:
         | I view it as more of a conceptual thing than a size issue. The
         | 74kb is a symptom of the issue, which is that bad things can't
         | be deprecated because of backward compatibility.
         | 
         | If there is solution that removes the necessity of a 74kb
         | package then I think we should embrace it.
         | 
         | I'm still fairly new to TypeScript but it's quickly replacing
         | Python as my daily driver for most things that aren't back-end
         | APIs.
        
         | moksly wrote:
         | I view it as more of a conceptual thing than a size issue. The
         | 74kb is a symptom of the issue, which is that bad things can't
         | be deprecated because of backward compatibility.
         | 
         | If there is solution that removes the necessity of a 74kb
         | package then I think we should embrace it.
         | 
         | I'm still fairly new to TypeScript but it's quickly replacing
         | Python as my daily driver for most things that aren't back-end
         | APIs, and Date is certainly one of those things I would love to
         | see changed.
        
         | thrower123 wrote:
         | I weep when I think of how many millions of times libraries
         | like jQuery, lodash, moment and so many others have been
         | downloaded and re-downloaded and re-downloaded again over the
         | decades.
         | 
         | A considerable fraction of all the data ever sent on the
         | internet is JS libraries that could have been bundled into
         | browsers instead of every web page using slightly different
         | versions.
        
       | adam_arthur wrote:
       | Anyone know why all new Ecmascript APIs are implemented to be
       | used as "newable classes" rather than ordinary functions?
       | 
       | The community seems to be moving towards functional
       | programming/away from classes.. and pretty much every mainstream
       | JS lib is function rather than class oriented (yes, I know
       | classes are simply special functions)
       | 
       | Also adds unnecessary verbosity/more syntax noise.
       | 
       | Is there some internal performance reason for why ordinary
       | functions couldn't be optimized to perform the same as "new"?
       | (Seems like it would be easy to wire the prototype internally to
       | the function, resulting in same semantics).
       | 
       | At this point better to be consistent, but I'd still use a date
       | library just to avoid added verbosity of this native solution.
       | Luxon API reads a lot better than this... Though I'm sure there
       | are reasons a standard implementation needs added complexity (has
       | to cover every edge case)
        
         | oaiey wrote:
         | Because most original API (DOM, browser, date, etc) are OO
         | oriented and you stick your standard library in one pattern.
         | 
         | And speaking of everyone moving to functional programming: i
         | work with several hundred developers in four continents in a
         | very dynamic envirnment.... And I have not seen a FP advocate.
         | Not that FP is not good (I prefer it where applicable) but
         | mindset/winning/moving towards are words I would not choose
         | when it comes to describing the state of FP and OO in the
         | world. There is a strong influence but not to a degree where an
         | established language changes its core paradigm: see Java, C#,
         | JS, ...
        
           | jacksnipe wrote:
           | Really? I have seen -- across many jobs and company sizes and
           | frameworks, over about a decade -- a slow but inexorable
           | trend of moving toward FP.
           | 
           | Be it in React, where hooks are pushing everything to be
           | functional; to the fact that Monads have started showing up
           | in unexpected places in codebases I've worked on; to the
           | fundamentally functional nature of frameworks I have to use
           | every day working at a FAANG.
           | 
           | Along the way, until the FAANG, I never met any functional
           | advocates. What I did meet are people who reach for the
           | appropriate functional tools when building solutions; others
           | see the much better solutions they arrive at, and copy.
        
           | lnxg33k1 wrote:
           | I would be more prone to say that the original API are
           | something that came up by using buzzwords from growing
           | languages or something else, for sure they're a thing, but
           | like it's not that `new` makes an OOP approach if then you
           | miss inheritance, abstraction, encapsulation and
           | polymorphism, I'm not sure if I am being picky but like if
           | there is just a keyword and nothing else more important to
           | the paradigm then I think it might be confusing for some
           | reader to see something like that statement
        
         | jitl wrote:
         | > Is there some internal performance reason for why ordinary
         | functions couldn't be optimized to perform the same as "new"?
         | (Seems like it would be easy to wire the prototype internally
         | to the function, resulting in same semantics).
         | 
         | Not particularly -- JIT vms should inline `(() => new
         | Thingy)()` as `new Thingy`. The temporal API provides a lot of
         | nice factory functions that don't need any `new` keyword. Here
         | are the first several examples of the Temporal API all
         | concatenated together with comments removed:
         | Temporal.Now.instant().epochSeconds;
         | Temporal.Now.instant().epochMilliseconds;
         | Temporal.Now.zonedDateTimeISO();
         | Temporal.Now.timeZone();
         | Temporal.Now.zonedDateTimeISO('Europe/London');         Tempora
         | l.Instant.from('2022-03-04T05:56:78.999999999+02:00[Europe/Berl
         | in]');         Temporal.Instant.from('2022-03-04T05:06+07:00');
         | Temporal.Instant.fromEpochSeconds(1.0e8);         Temporal.Zone
         | dDateTime.from('2025-09-05T02:55:00+02:00[Africa/Cairo]');
         | Temporal.Instant('2022-08-05T20:06:13+05:45').toZonedDateTime('
         | +05:45');         Temporal.ZonedDateTime.from({
         | timeZone: 'America/New_York'           year: 2025,
         | month: 2,           day: 28,           hour: 10,
         | minute: 15,           second: 0,           millisecond: 0,
         | microsecond: 0,           nanosecond: 0         });
         | 
         | It seems like the style is to provide these factory functions
         | for almost every use-case except "build me a specific object
         | with these exact values", which you need to use `new
         | Constructor(...)` for. Where is the noise?
         | 
         | As a side note, there are concrete performance reasons to use
         | class/prototypes over plain objects or closure-over-hidden
         | state in your own code:
         | 
         | - Class and/or constructor functions helps ensure your long-
         | lived objects instantiate their properties in a regular order.
         | V8 has trouble unifying objects with the same properties but
         | different property orders into the same hidden class. Each
         | hidden class costs JIT time and memory space, so minimizing
         | both is nice. You can fix this yourself by forcing
         | instantiation of a value to go through a factory function to
         | normalize property order, but at that point, why not use a
         | class to take advantage of `instanceof`?
         | 
         | - Closures over hidden state, eg long-lived closures you would
         | use to implement your own object system over enclosed local
         | variables, cost more than plain objects or class instances.
         | It's more straight-forward to define classes at the top level
         | and wrap them in sugared factory functions than to code-review
         | factories that manually build objects with function properties.
        
           | adam_arthur wrote:
           | You've covered a lot here, but just want to comment on a few
           | things.
           | 
           | Factory functions can return objects that have a prototype
           | just the same as "new", there is no inherent reason object
           | constructors should require "new". Given that most of modern,
           | idiomatic JS relies on factory functions, it seems very
           | inconsistent to me to then randomly require invoking "new" to
           | construct an object.
           | 
           | Why not simply Set([1, 2, 3])? The noise comes when you have
           | a nested expression with random "new" statements sprinkled in
           | which disrupts the flow. Though I agree that overly complex
           | expressions are an anti-pattern
           | 
           | My underlying point is that "new" does not provide any
           | clarity, given that objects are created and returned all the
           | time without "new", so represents an inconsistency in design
           | to me. The presence or absence of "new" basically tells you
           | nothing, except implying that the object likely has prototype
           | functions. But whether or not they are prototyped is more of
           | an implementation detail anyway.
           | 
           | I agree with you that most of Temporal has factory functions
           | that obviate "new".
           | 
           | To your point on performance of closures, this isn't going to
           | materially matter for majority of use cases. Yes, prototype
           | is more efficient than closures functions, but benefits of
           | prototypes can also be achieved through separation of data
           | and function (singleton utility functions that operate on
           | data).
           | 
           | Also syntax sugar for prototype could have been done in an
           | (IMO) more consistent way through some syntax addition to
           | functions rather than creating class. Generally modern
           | userland code shouldn't really be using prototype and "this"
           | anyway, as "this" has tons of footguns in JS, and I would
           | guess majority of developers don't understand the intricacies
           | of "this" when passing functions around, or when using arrows
           | vs classical function declarations.
        
           | olliej wrote:
           | The problem with relying on JITs inlining things is that
           | you're hoping that an opaque optimizer will come to the same
           | conclusion as you, and historically there have been all sorts
           | of things that spontaneously kill optimizations (I recall
           | there being a point where one of the JS VMs made decisions
           | based on source text size, so comments could change
           | optimization behaviour).
           | 
           | There's also all sorts of optimizations you have to depend on
           | to avoid excess object allocations, etc.
           | 
           | That said object allocation in JSC and V8 (not sure about
           | spider monkey) is essentially a pointer increment in the
           | common case, so its not exactly expensive.
        
         | 323 wrote:
         | One good reason is to avoid polluting the global namespace.
         | 
         | Otherwise you end up like Mathematica, which has ten thousand
         | or so functions in a single namespace.
         | 
         | Or PHP which had (has?) a similar problem (but on a smaller
         | scale).
        
           | paavohtl wrote:
           | You can easily split stuff into modules without getting
           | classes involved. For example the `Math` module which has
           | been in JS basically forever.
        
           | adam_arthur wrote:
           | But they are on the global namespace. E.g. new Set() is same
           | as new window.Set()
        
             | 323 wrote:
             | Right, but just the constructor. Everything else is a
             | method of Set/Temporal.
        
         | bern4444 wrote:
         | The Temporal API supports a `from` method/function on most of
         | the options - that's very much the functional approach to avoid
         | `new`.
         | 
         | Often objects that are class based will expose a `of` or `from`
         | method that abstracts over the `new` keyword `Array.from()` is
         | one example instead of `new Array()` (of course the most common
         | way is `x = [1, 2, 3]` but these other options exist too).
         | 
         | This seems fairly functional to me.
        
         | newlisp wrote:
         | Because they are obsessed in converting JS into Java.
        
           | adam_arthur wrote:
           | It's been a bit of a headscratcher for me.
           | 
           | I was quite against adding the class keyword to begin with to
           | be honest.
           | 
           | Think a lot of that came at the tail end of the "JavaScript
           | is terrible" generational mentality, and the idea was to copy
           | other languages rather than improve what they had
           | independently.
           | 
           | To be clear, having additional functionality is fine in and
           | of itself, but now the waters are mudied between function
           | oriented and class oriented approaches, and by and large
           | community seems to be settling on function oriented.
           | 
           | In the end, class just created unnecessary fragmentation.
        
             | egeozcan wrote:
             | I was also happy with prototypes, now when I use them, and
             | I use them rarely, other developers look at my code like
             | black magic and my "others should be able to understand my
             | code" circuit breaker kicks in and I convert it to a class.
             | 
             | Is it more readable? Yes.
             | 
             | Do I feel like we are dumbing JS down? Yes.
             | 
             | Is it worth it when we consider that it helps onboarding
             | hundreds of thousands of developers who want to choose JS?
             | Oh f* yes!
        
               | adam_arthur wrote:
               | Creating prototypes in general is not necessary for 99%
               | of JS code. Using completely cloned/closured functions
               | will perform just fine for the majority of use cases...
               | And the code there reads very simply... Just a function
               | that returns an object that has functions.
               | 
               | Or you can simply separate out functions into utility
               | objects rather than attaching to the specific data
               | object, and performance should be the same as using
               | prototype, without any of the special syntax
               | 
               | This model of programming is also much simpler, I'd
               | argue. There is no use of "this", everything is explicit.
               | Especially in JS, "this" sucks because the semantics
               | change depending on whether you use function declarations
               | or arrow functions. And "this" will also reference the
               | caller, so changes if the function gets passed around.
               | Much more obvious to pass an explicit argument to a
               | function than to rely on "this"
               | 
               | I do agree there are use cases where prototypes are more
               | useful, performance sensitive games/server code etc. But
               | pretty rare that you can't take one of the approaches
               | described above. And people writing performance sensitive
               | code aren't generally also going to be the newbies.
               | Additionally, could have had syntax sugar for functions
               | that wired prototype without the new/class paradigm,
               | which I argue just adds unnecessary verbosity to the
               | language.
        
               | egeozcan wrote:
               | I was just replying to the class vs prototypes part.
               | There usually is a once-in-a-year situation that is
               | solved better with classes, so I somewhat agree with your
               | 99% code doesn't need it estimation.
               | 
               | Also I should mention that in the rare case when I did
               | use the prototypes, I always used the adapter pattern (an
               | adapter function that takes a slice of "this", calls an
               | independent function, and merges it back to "this"), it
               | was easier to test.
               | 
               | But people are so unused to declaring dependencies as
               | parameters (even function dependencies aka services),
               | they cry untestable whenever they see independent
               | (static) functions. I know this from the PHP, Java and
               | .NET world. To this day, it didn't help to explain what
               | they call DI is just passing parameters (but rather more
               | bureaucratically).
        
               | wruza wrote:
               | What you propose will likely drive the code to functional
               | equivalent of FacadeAdapterArrayController, but written
               | not only once but in every line of code. Because think of
               | what even a simple .filter().map().filter() would expand
               | into. Of course we can just _stream()_ or | everything,
               | but the original "simple functions" idea will quickly get
               | lost in the woods.
        
               | adam_arthur wrote:
               | Not clear how you're reaching that conclusion. Native
               | constructs can still implement prototype methods
               | transparently to the developer without the class keyword.
               | Just as devs could in userspace.
               | 
               | But contrary to what you're saying, most popular userland
               | libs are indeed function oriented, and they don't end up
               | like you're suggesting. E.g. RxJS, lodash
               | 
               | By function oriented in this context, I mean that they
               | don't rely on the new keyword for ordinary code. Which
               | reads cleaner
               | 
               | Anyway, functional stdlib can be pretty clean, such as
               | something like Stream(persons).filter(person =>
               | person.age > 18).map(person => person.firstName).
               | 
               | Also there's the Pipes spec in the works that would allow
               | for chaining distinct functions that are not on same obj.
               | Not sure of current status
        
           | lowwave wrote:
           | For sure, do also see cases where class can be good working
           | with a larger team. However, since js's biggest advantage is
           | function as a first class citizen, I do feel like they ought
           | to make the API to be functional., however OO design may
           | attract more developers coming from OO programming world.
        
         | wruza wrote:
         | First, how do you tell a date from a string or a number easily
         | in the code. Second, the functional thing happens for many
         | reasons, and biggest ones are practical. You can't DCE
         | (treeshake in hipsterish) classes in js due to highly dynamic
         | semantics, but builtin code doesn't suffer from that. If it was
         | a non-special type, then _maybe_ it was worth just Foo(), but
         | usually there are some methods attached to it as well as
         | introspection capabilities like toJSON(), toString(), etc.
         | 
         |  _The community seems to be moving towards functional
         | programming /away from classes_
         | 
         | The community moves to where React is, no real CV choice. Other
         | parts of the community are non-functional, e.g. new
         | WebpackPlugin, etc.
        
           | adam_arthur wrote:
           | The community was in the functional space before react.
           | Angular 1 was very function oriented too, and relied heavily
           | on ordinary functions and closure scope rather than class.
           | And then everybody latched onto class in the phase of time
           | between angular 1 and next gen frameworks.
           | 
           | Class was something pushed by all the next gen framework
           | authors at the time. Then most next gen frameworks abandoned
           | class, because it proved to be worse in many ways than
           | ordinary functions did. Which was the position I held at the
           | time, and seem to have been borne out.
           | 
           | The easy way to tell types apart in ordinary JS is to have
           | consistent naming conventions. If you always name things such
           | that the name implies the type (not Hungarian style, but more
           | natural language oriented), you can infer the type from the
           | name correctly 90% of the time. E.g. always write arrays as
           | plurals, map-like objects as keyToValue, and so on.
           | 
           | But the easier answer is to just use Typescript.
           | 
           | Inferring type from instantiation point is pretty meaningless
           | anyway. The type needs to be inferrable at the consumption
           | site to be readable, not the production site. Understanding a
           | type only matters in the context where it's used
        
             | chipsa wrote:
             | > (not Hungarian style, but more natural language oriented)
             | 
             | Apps Hungarian wasn't actually a stupid idea. It just got
             | bastardized into Sys Hungarian, which was. Apps Hungarian
             | could tell you whether the string was unsafe (and needed to
             | be sanitized), or safe to use. Or tell you if the integer
             | type you were using was an offset, or a row number, or
             | whatever. It was supposed to give you semantic info that
             | wasn't necessarily obvious from the given type.
             | 
             | Sys Hungarian told you that you were using a long pointer
             | to a zero terminated string. But not what the string
             | actually meant. It just regurgitated the type of the object
             | again.
        
         | olliej wrote:
         | What do you mean by ordinary functions? There has to be some
         | value to represent a date or time that you pass around, so
         | something somewhere has to return it.
         | 
         | If your concern is `whatever(date)` vs `date.whatever()` then
         | the issue you run into is pollution of the global object, which
         | is bad, and frequently not possible due to naming collisions
         | with existing sites (fun story, `let` required some exciting
         | rules to deal with existing content using variables named
         | `let`). Given an inability to add a million new functions to
         | the global object your concise `whatever(date)` becomes
         | `Temporal.whatever(date)`
        
         | LAC-Tech wrote:
         | > The community seems to be moving towards functional
         | programming/away from classes..
         | 
         | Anecdotal observation follows:
         | 
         | In the span of my career so far it looks like the community
         | moved from imperative programming with a few classes/prototypes
         | sprinkled in there, to imperative programming with a few
         | lambdas and HOF sprinkled in there.
         | 
         | I've yet to come across anything significantly functional or OO
         | in the wild, it's still mostly plain old data mutable
         | structures and for loops.
        
       | livinglist wrote:
       | I kinda agreed
        
       | devadvance wrote:
       | Excited to get to use this. One area of concern is i18n. The
       | article touches on this briefly at the end, but I hope a zoned
       | value can be used with Intl as well; having to use only Plain
       | values would be frustrating.
        
       | tmikaeld wrote:
       | Awesome, hoping to see this in Cloudflare Workers as soon as V8
       | has it! (Currently using day.js)
        
       | TameAntelope wrote:
       | > Modern alternatives such as Day.js and date-fns may be better
       | but should a library necessary when your app has minimal date-
       | handling requirements?
       | 
       | Yes? Or at least, I don't think this is the, "obvious question
       | that leads to the rest of the article" that the author may have
       | assumed.
       | 
       | As another commenter mentioned, Day.js is 2kb. That's the answer:
       | use Day.js.
       | 
       | But I guess that doesn't get you a blog post you can reference
       | when applying to jobs, so here we are.
        
         | nobleach wrote:
         | From someone who used MomentJS back in the day, Day.js is such
         | a nicer alternative! Moment was like 59k or something!
        
       | the__alchemist wrote:
       | Both the builtin lib, and the popular moment lib are missing
       | separate date and time types, which leads to subtle errors. (ie
       | when using their workaround of using datetime types for either).
       | From the article, it appears Temporal has the same problem.
       | There's nothing wrong with mutable types, which is common in JS
       | discussions; the problem is when the API mutates in place where
       | this isn't obvious.
       | 
       | I hand-wrote date and dt types with basic operations instead.
       | Limited functionality, eg timezones, formatting etc, but behaves
       | as you'd expect.
       | 
       | Another option might be to wrap Rust's Chrono lib in WASM, then
       | call from JS; it's the best DT lib I've seen in any language.
        
         | spankalee wrote:
         | There is a separate time type: https://tc39.es/proposal-
         | temporal/docs/plaintime.html
        
           | the__alchemist wrote:
           | Awesome. It looks like it has a PlainDate type as well.
        
       | yashap wrote:
       | Nice, it looks to be quite similar to the Java 8 date/time APIs
       | (java.time.*), which are excellent. Looking forward to this!
        
         | ferdowsi wrote:
         | Ironic because Javascript's Date behavior was also modeled
         | after the original java.Util.Date (which was immediately
         | deprecated, whoops).
        
           | stickfigure wrote:
           | Why is that ironic?
        
             | lstamour wrote:
             | Because copying Java got them into this mess? ;-)
        
               | yashap wrote:
               | Yeah, but the Java 8 date/time API has been around for
               | ~7-8 years, and is basically universally loved, while the
               | original java.util.Date was hated for ages. Plus Java 8
               | date/time is based extremely strongly on joda-time, which
               | hit 1.0 about a decade before that, and was also pretty
               | universally loved.
               | 
               | So we're dealing with an API that has been considered
               | great, and an excellent way to deal with dates/times, for
               | nearly 2 decades. Seems like a safe bet to copy :)
        
         | bluedevil2k wrote:
         | There's a direct JS port of Java time as well - https://js-
         | joda.github.io/js-joda/
        
       | mikeocool wrote:
       | Wahoo, it doesn't use 0-indexed months! Probably the biggest
       | cause of bugs with js Date objects.
        
         | mkotowski wrote:
         | That does remind me: why that even is a thing? Ordering days of
         | a week from zero can make sense since there is Monday/Sunday as
         | a week start divide, and this can be seen as a bypass (0/7 as
         | Sunday and 1 as a Monday), but with months?
        
           | tshaddox wrote:
           | Zero indexing for arrays/collections generally makes sense.
           | If you had the months in a normal array they would obviously
           | be zero-indexed (unless you deliberately put a placeholder
           | value in the first position in the array, which would be
           | pretty weird since all the normal ways of getting the first
           | thing in the array would break).
           | 
           | The reason it apparently feels weird to many people to have
           | months be zero indexed is that months are often _referred to_
           | by their ordinal number, and ordinal numbers obviously start
           | at 1.
        
             | yunohn wrote:
             | > months are often referred to by their ordinal number
             | 
             | What do you mean by "often"? Humans always use ordinal
             | numbers for counting things like months, days, weeks, etc.
             | There is no concept of 0 to be applied here, except for
             | programming array indexing purposes.
        
               | tshaddox wrote:
               | What I mean is that people use the ordinal number as the
               | _name_ of the month (as well as the day of the month). If
               | you ask someone their birthday they'll often say
               | something like "five twenty, nineteen eighty-four."
               | 
               | This is a potential cause for confusion when writing
               | computer code, because it's very common for code to refer
               | to items in a collection starting at zero.
        
               | kevin_thibedeau wrote:
               | It is lifted from C's struct tm. If you're maintaining
               | tables of month names you're going to 0-index them so
               | tm_mon is 0-based to facilitate that.
        
               | istjohn wrote:
               | Lay people indicate the month with an ordinal all the
               | time since it's how dates are standardized (12/30/2021).
               | People don't often indicate the day of the week with a
               | number, they use "Monday" or "Tuesday". So there's no
               | strongly held convention in people's minds about how to
               | number days like there is for months.
        
             | WA wrote:
             | Even if this is true, days in JS still start at 1. It is
             | inconsistent.
        
           | lucian1900 wrote:
           | The week starts on Monday in most of the world.
           | 
           | Date & time APIs must match local reality.
        
             | pavel_lishin wrote:
             | When reality differs by locales, at least one "local
             | reality" won't match the API.
        
           | mikewhy wrote:
           | https://stackoverflow.com/a/41992352
        
             | SippinLean wrote:
             | > it was copied from Java's JDK1.0 (1995) java.util.Date,
             | which also had this quirk
        
               | jauco wrote:
               | No. It's definitely older than that.
               | 
               | https://mobile.twitter.com/hillelogram/status/13292284196
               | 289...
        
               | mikeryan wrote:
               | Just because the issue predated Java doesn't preclude the
               | fact that the initial JavaScript Date implementation was
               | lifted from java.util.Date. Brandon Eich has explicitly
               | stated it was so.
               | 
               | https://maggiepint.com/2017/04/09/fixing-javascript-date-
               | get...
        
               | Taywee wrote:
               | Twitter is such a bad platform for this. Code in images
               | means it's completely inaccessible to the blind and very
               | inaccessible to people with poor vision, and you can't
               | copy and paste it into an editor for syntax highlighting
               | or better examination.
        
           | [deleted]
        
         | matsemann wrote:
         | Another one is JS parsing numbers with leading zeroes as octal
         | (unless specifying base, which is why linters are so strict on
         | it). Often surfaces when parsing date strings.
        
           | toomanybeersies wrote:
           | That hasn't been the case in JS for almost a decade.
           | 
           | parseInt('0700') returns 700. But parseInt('0x700') will be
           | parsed as octal, so now it's just a more subtle gotcha.
           | 
           | Loose parsers (such as parseInt(), and Date.parse() in JS)
           | are one of the worst ideas ever. Nothing like tracing a bug,
           | and finding that a junior dev is trying to parse DD/MM/YYYY
           | strings using Date.parse(), except that instead of throwing
           | on trying to parse an incorrect [non-RFC] format, the parser
           | makes a best-guess and propagates an incorrect date because
           | it was parsed as MM/DD/YYYY.
        
             | alkonaut wrote:
             | Not sure why any api ever had functions like float.parse(s)
             | or date.parse(s). Even more modern ones like .NET (circa
             | 2000) had it. And it's literally _never a good idea_. Not
             | even for a one off script is it convenient or ergonomic to
             | omit the information about what format you expect (or try
             | to suck it out of thin air such as a static locale on the
             | thread). It 's just a bad.idea. If it does accept date
             | parse(s) it has to be with a fixed format (e.g. iso) unless
             | specified. Not "system local format" or something. The same
             | applies to number formatting. I haven't met one single
             | person who prefers automatic string formatting to switch
             | decimal point and decimal comma due to the system language.
        
               | olliej wrote:
               | Why would you not have a parseFloat/float.parse/whatever?
               | 
               | Parsing floating point values correctly is not a trivial
               | amount of work - to the extent that there have any been
               | security vulnerabilities in implementations.
        
               | matsemann wrote:
               | They are not arguing about the stdlib including them, but
               | the api they choose. Instead of parseFloat(str) that
               | tries with a system dependant comma or period, have the
               | decimal type be a parameter or have two explicitly named
               | functions.
               | 
               | Same with dates. Don't try lots of formats on an
               | arbitrary string, force the user to specify the expected
               | format somehow.
        
               | alkonaut wrote:
               | Of course it should be a api but it should be either
               | explicitly requiring a format OR (more likely) default to
               | an invariant format.
               | 
               | That is, if I do this                   float f =
               | 123.456;         Console.WriteLine("value is "+f);
               | 
               | The output shouldn't vary depending on whether it's run
               | in France or the US (which it does by default).
               | 
               | For parsing, the argument should even be explicitly
               | required I think. So                   float f =
               | Float.Parse("1,23",  frenchLocale);
               | 
               | So that it's not ever forgotten or the reader has to
               | wonder if the author forgot it.
        
               | olliej wrote:
               | JavaScript's numeric parsing is locale independent.
               | People write too much code blindly to make any kind of
               | locale inference anywhere.
               | 
               | Otherwise I agree with you whole heartedly - I have been
               | stung by absurd locale dependent behaviour in the past
               | (windows' font loading APIs inexplicably translate the
               | font variant _in the programmatic api_ )
        
               | toomanybeersies wrote:
               | I wonder how much of that has to do with the fact that
               | ISO8601 was relatively newer back then (published 1988),
               | and date formats were much less standardised 20+ years
               | ago.
               | 
               | For instance, RFC 1945 (HTTP 1.0) specifies three
               | acceptable date formats. Add ISO dates, and now you're
               | writing software that needs to handle 4 different
               | formats. Easier to just use a heuristic parser that's
               | capable of accepting HTTP, email, Usenet, and ISO
               | timestamps.
               | 
               | Fortunately, these days it's generally considered a bad
               | idea to use anything but ISO timestamps, with the
               | exception of a former colleague who tried arguing that
               | DD/MM/YYYY was an acceptable format to be transmitting
               | and storing dates in.
        
         | postalrat wrote:
         | Years aren't 0-indexed either. Nobody has a problem with that.
        
       | llimos wrote:
       | Betteridge's law does not apply here!
        
       | dragonwriter wrote:
       | Temporal is great, and the sooner it lands and is usable the
       | better (AFAIK, there isn't a production-grade polyfill yet.)
       | 
       | In the interim, JS-Joda [0] seems pretty decent, and doesn't use
       | the wrapper approach.
       | 
       | [0] https://js-joda.github.io/js-joda/
        
         | httgp wrote:
         | My favorite has always been Day.js [0] - it is really small,
         | has a very clean API, great documentation and does pretty much
         | everything I want.
         | 
         | [0] https://day.js.org/
        
           | moogly wrote:
           | Used that as a replacement for momentjs until we had to make
           | things seriously timezone-aware, and some quite crippling tz
           | bugs (granted, probably 2 years ago now) made us move to
           | Luxon. That worked well, but I'm glad to have something
           | JodaTime-ish coming now that doesn't conflate instants with
           | zoned datetimes with durations.
        
           | aidos wrote:
           | It's not really the same thing though, right? It doesn't
           | handle instants vs zonedtimes etc.
           | 
           | Even the simplest of future cases is handled poorly by these
           | other libraries. If you want to say that something happens on
           | a certain date in the future (say, a due date), your only
           | option is to use an instant as an approximation (often
           | midnight utc on that day). It works ok, but you're better to
           | have a proper datatype that represents a day without a time
           | and timezone component (it's effectively a 50hr ish window).
           | Temporal gives you all that and more.
        
         | aidos wrote:
         | I've been keeping an eye on it myself. The implementation in
         | Chrome looks pretty complete already, which is promising.
         | 
         | I don't quite get the point of the other libraries like moment
         | etc. They have a bunch of convenience stuff, but unless you've
         | modelled the different _types_ of times that crop up in real
         | life, it's all a bit pointless. When I first read through the
         | Temporal api, I was physically nodding along in agreement. It's
         | dates and times done right in js. Can't wait to be able to use
         | it.
        
       ___________________________________________________________________
       (page generated 2021-12-30 23:01 UTC)