ryenus 6 years ago

So it's a better moment made by the moment team:

https://moment.github.io/luxon/docs/manual/faq/moment.html

Major differences:

  * Immutable
  * Months in Luxon are 1-indexed instead of 0-indexed like in Moment and the native Date type.
  * Localizations and time zones are implemented by the native Intl API (or a polyfill of it), instead of by the library itself.
  * Luxon has both a Duration type and an Interval type. The Interval type is like Twix.
  * Luxon lacks the relative time features of Moment and will until the required facilities are provided by the browser.
  • notaboutdave 6 years ago

    This is an excellent rewrite, but I'm hesitant to try it because Moment doesn't emphasize speed.

    I'm in need of a fast date and time library (close to realtime) and have reluctantly rolled my own until I find a better option.

    • icambron 6 years ago

      For what it's worth, there's no code (edit: well, maybe a few lines) in common between the libraries; Luxon is written from scratch. I haven't done a ton of perf testing, but depending on your use case, I'd expect most operations to be much faster in Luxon. The caveat there is that Moment objects are mutable, which can sometimes be a perf advantage.

    • tonyhb 6 years ago

      Have you tried date-fns (http://date-fns.org/)? One good thing is that they bundle every module separately, so you can only import what you need.

  • neals 6 years ago

    In what situation is immutable important?

    • icambron 6 years ago

      I think there are lots of good reasons to make datetimes immutable (e.g. many of the same reasons most languages make strings immutable). But here's one specific to Moment and Luxon: chainable APIs should really always have immutable types because the return value is the thing you use next anyway. When each call returns an instance of the type it's both completely unnecessary and very often harmful for those calls to modify anything.

        var a = moment();
        console.log("the end of tomorrow is", a.add(1, 'day').endOf('day'));
      
        // do more stuff with a
        // oh crap, a is now set to tomorrow? wtf?
      
      If you want a to be the end of tomorrow, all you needed to do was assign a to the whole chain, so this mutation didn't help you. That add() and endOf() return instances of Moment signals that they are Moment -> Moment functions, not mutators that also return the object. A mutable API should have void methods:

        var a = moment();
        a.add(1, 'day');
        a.endOf('day');
      
        // do stuff with a
    • raspasov 6 years ago

      Dates and times are values by definition, not mutable objects that can be changed via methods. The year 2017 is 2017. It represent a moment in time, or more precisely a period of time between two points. The year 2017 does not “become” 2018 when you .add one year to it. Fully immutable objects are also easier and simpler to compare since they are, again, values. 2017 is 2017, always. Not using proper immutability leads to an “object identity” crisis where everything is anything. An infinite amount of years 2017 are allowed to exist by default(!) and they are not easily comparable or require specific library APIs to allow that.

icambron 6 years ago

Luxon author here, happy to answer anything.

Edit: Here's a thing I wrote about why this exists: https://moment.github.io/luxon/docs/manual/faq/why.html

  • seanp2k2 6 years ago

    When can you make a Python version available? Datetime is by far my biggest gripe with Python. It takes many times the lines of code to do something “simple” with it vs other languages (e.g. parse remote time stamp in a specific format, apppend time zone info to that, get local time + zone, normalize both to UTC, compare, present difference in human-readable format).

    Here’s the python version of moment: https://github.com/zachwill/moment/blob/master/README.md

    • BrandoElFollito 6 years ago

      Have you tried arrow (my favorite), dolorean or a third one the name escapes me right now?

      I use arrow whenever I need to process a date, no matter the usage. Having a consistent interface is golden.

      EDIT I just realized that the author of moment in Python (you link to) also mentions arrow. I have to remember the name of the third package, it addressed some weaknesses in arrow (particularly issues with failed parsing which does not output an error)

    • icambron 6 years ago

      I'm not much of a Python person, but it seems like someone could port it without too much trouble. In particular, you wouldn't have to use the ugly tricks I used to make the time zone stuff work

  • notaboutdave 6 years ago

    First of all, thanks for sharing your great work.

    The support for non-Gregorian output is interesting. Are there any plans to extend full support beyond Gregorian? For example, something like:

      dt.plus({months: 7, calendar: 'hebrew'})
    • icambron 6 years ago

      Thanks!

      No, there's no plan to do that. The trouble is that Luxon has no idea how the Hebrew calendar works; it only knows how to output the non-Gregorian stuff because your browser already can via the Intl.DateTimeFormat API. Luxon finds some interesting ways to abuse that API to add some neat features like internationalized parsing and full time zone support, but there's a limit there. To add 7 Hebrew months, Luxon would actually have to be able translate arbitrary Hebrew dates into timestamps, and I can't think of a way to make it do that without any real knowledge of the calendaring system.

  • nevir 6 years ago

    No questions - just a huge thanks for doing this!

tommikaikkonen 6 years ago

I've migrated a lot of code from moment to date-fns because of moment's bulky size and vast, mutable API. Luxon seems to fix the API issue. date-fns is still great for simple operations, but I'll definitely consider this for new projects with nontrivial datetime handling.

  • spraak 6 years ago

    Yes, mutation in Moment has burned me a few times before I realized that occurs.

    Edit: wow, I just looked at the repo and realized its made by the Moment team. That might be pretty cool.

ianstormtaylor 6 years ago

How does this compare in file size to Moment? That's the only real issue I have with it.

  • dawkins 6 years ago

    If you only want timezone conversions I removed everything else from Moment. It's less than 2KB uncompressed: https://github.com/scorredoira/timezone.js

    • pitaj 6 years ago

      I my experience the actual timezone information is the heaviest portion of the payload. I can't wait until all browsers have support for `Intl`

      • seanp2k2 6 years ago

        That any computers talk to each other about time in any other terms than epoch is insane to me. From there, converting it to local time zone is pretty easy, but it should be a presentation-layer ONLY thing. If you’ve ever worked with or implemented a system where this wouldn’t work, I’m interested in hearing about why.

        • CodesInChaos 6 years ago

          If you schedule a meeting in the future you typically agree on a local time in a specific timezone. So the (local time, timezone) tuple is the authoritative value you want to store (you can cache the utc time if you want).

          Just storing the utc time and timezone is problematic, since the conversion function between utc and local can change via tz database updates, sometimes with little notice (Israel is notorious for sometimes only deciding on the DST switching date shortly before it happens).

          In principle you could store (utc-time, offset used to convert from local, timezone), but I find that rather unintuitive and error prone, since it doesn't cleanly separate authoritative from cached values.

        • icambron 6 years ago

          Ideally, yes. There are a lot of times you need it though:

          1. Recurring meeting events have to take place in a certain zone so that the right epoch time can be calculated for the recurrences across DSTs

          2. Even single meetings need them (see other post in this thread)

          3. You may need other zone's local times. Imagine you're scheduling shifts for people to work. If you're in a different zone than work is scheduled in, the presentation later needs to know that zone to compute the right epoch times.

        • pitaj 6 years ago

          Ah, sorry. I was speaking more in terms of internationalization than actually converting between time zones. All you need is a database, but that database can be hard to maintain and can be very large.

        • alphaalpha101 6 years ago

          That anyone uses UTC for anything where it isn't relevant is insane to me. If I schedule a meeting in local time, then it's in local time. It has nothing to do with UTC. It's local time at the beginning, middle and end.

  • pygy_ 6 years ago

    After minification with Uglify:

    27.3 KB compressed with `gzip -9`, 26.4KB with `zopfli -i1000` and 24.0KB with `brotli -q 11`.

    (kilo, not kibi)

    • icambron 6 years ago

      I'd love to make it smaller. Several of the builds contain polyfills for newish JS features not supported in IE. I'd like to strip that out and shave off a few k.

    • collectively 6 years ago

      TIL they just completely redefined a kilobyte a while ago.

      • orf 6 years ago

        Can you elaborate?

        • collectively 6 years ago

          At some point, a kilobyte was 1024 bytes. Now, a kilobyte is 1000 bytes, and 1024 bytes is a kibibyte.

          I mean, it does make sense. But it just sounds off to me.

          • seanp2k2 6 years ago

            Hard drive manufacturers have been doing this for decades. This is why the “80GB” drives were 74.5GB in Windows.

            It’s more complicated with SSDs: https://www.anandtech.com/show/2829/7

            EDIT: the official “kibibyte” was standardized in 1998: https://physics.nist.gov/cuu/Units/binary.html so almost 20 years ago. Blame Windows and HDD mfgs for sticking with the SI definitions.

            • sd8dgf8ds8g8dsg 6 years ago

              Yea, bad bad windows for following standards.

              The SI prefixes are well established before 1998 and the cause for this brainmelt.

              https://en.wikipedia.org/wiki/Metric_prefix

              • CodesInChaos 6 years ago

                Windows (at least up to 8) does not follow the SI standard. It uses KB, MB, GB but converts using 1024. Which has funny consequences, like 999MB being smaller 0.94GB.

              • collectively 6 years ago

                Well to be fair “GB” could refer to either prefix.

    • hjnilsson 6 years ago

      So actually larger than moment (which is 16.3kb gzip)? Hopefully it will improve over time.

      API looks better than moment though.

bshimmin 6 years ago

Months in Luxon are 1-indexed instead of 0-indexed like in Moment and the native Date type.

This seems like a bold decision and terrifying source of errors for those of us with decades of experience thinking January is 0.

  • Gaelan 6 years ago

    OTOH, as somebody who doesn't do much date stuff JS/moment's months are a constant source of bugs.

  • hectorlorenzo 6 years ago

    I think that moment.js was already built that way. For me it kinda makes sense: if days are calculated with a 1-index in mind, why make months different? As I said: it KINDA makes sense.

    • icambron 6 years ago

      No, they're 0-indexed in Moment. But yes, the reason I made Luxon 1-index them is that days and years are 1-indexed. I also fielded a lot of issues in Moment that were caused by newer programmers not knowing that months were 0-indexed.

    • frutiger 6 years ago

      I'm not defending the difference between how months and days/years are treated. But here are some possible reasons.

      From ctime(3):

          Broken-down time is stored in the structure tm, which is defined in <time.h> as follows:
      
              struct tm {
                  int tm_sec;    /* Seconds (0-60) */
                  int tm_min;    /* Minutes (0-59) */
                  int tm_hour;   /* Hours (0-23) */
                  int tm_mday;   /* Day of the month (1-31) */
                  int tm_mon;    /* Month (0-11) */
                  int tm_year;   /* Year - 1900 */
                  int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
                  int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
                  int tm_isdst;  /* Daylight saving time */
              };
      
      Also, it allows you to do things like

          ["JAN", "FEB", ..., "DEC"][theDate.month]
      • semi-extrinsic 6 years ago

        Well, nobody is confused when their digital watch reads "00:00:00" as the ball drops on New Years Eve. But if the date was 2018-00-01 people would be like "WTF??"

  • edoceo 6 years ago

    ISO 8601 say January is 01

    • tomjakubowski 6 years ago

      Jeez, to think I've been using base 10 this whole time!

  • dwg 6 years ago

    As explained on the website, that's why this is Luxon and not moment 3.0. It's a great approach for them to take that allows them to experiment, grow, and relieve the pressure from calls for change, without disrupting the existing community.

  • tobyhinloopen 6 years ago

    No, Javascript is the terrifying source of errors here.

  • alphaalpha101 6 years ago

    Months should always be 1-indexed. Years are, days are, why not months?

bastijn 6 years ago

Not a direct js dev so forgive my ignorance. How does this compare to moment.js [0]? Any feature differences?

[0] https://momentjs.com/

  • Osmose 6 years ago
    • bastijn 6 years ago

      Thanks. This link should be on the github page to be honest. For people like me who do not (always) click through if they don’t see an immediate need. Only now notice the url contains moment and this is part of moment.

  • dwg 6 years ago

    For me and I'm sure others one of the most important differences is immutability. This has been a big request from the community, but would be impossible to implement in moment without breaking much code which relies on the current mutability.

    https://github.com/moment/moment/issues/1754

lolc 6 years ago

Ah, immutable. Mutability is my biggest issue with Moment.js. It seems they have kept the API mostly the same, so this will be easy to replace.

jazoom 6 years ago

Interesting. It looks like this is maintained by the maintainers of moment.

k__ 6 years ago

How does it compare to date-fns?

  • hobofan 6 years ago

    Biggest remaining difference I can see is that Luxon still has it's own classes while date-fns operates on bare DateTime objects (AFAIK), which allows for a different kind of API. So it's mostly a matter of personal preferences now.

feiss 6 years ago

Funny. All libraries/frameworks nowadays qualify themselves as 'modern'.

rplnt 6 years ago

Sorry for the dumb questions, I haven't worked with js much, but what does this add to the standard library?

Going just by the one example there, I can see that timezone by location is probably extra, that's perfectly fine. The endOf modifier seems more like a helper to fix broken date/time model in js? But other parts should probably be in the standard library? I was under the impression js is improving fast nowadays, will stuff like this get into the language?

  • icambron 6 years ago

    The standard library is really difficult to work with and does very little for you. There are some improvements to Dates coming through the standards pipeline but it will be a while.

  • foota 6 years ago

    From what I've seen JavaScript's standard library doesn't change much, most the changes are language changes?

    As for what it adds, looks like duration and interval classes.

tobyhinloopen 6 years ago

2017. We have async, promises, classes, => functions in Javascript, but we still have abysmal date & time support and 100 libraries to solve it.

This library looks less bad than momentJS' tangled ball of mud. Good job

cel1ne 6 years ago

PLEASE use joda-js on Javascript: https://js-joda.github.io/js-joda/

It's a port of the java8 date/time API, which is the most correct date-handling library there is.

  • jazoom 6 years ago

    What if one does not want to use a port of Joda? Even looking at the documentation makes me run away. Where are all the examples?

    date-fns seems good, moment works well too, despite its flaws, this new one is worth looking at.

    Dismissing all other libraries isn't very helpful.

    And yes, I realise all other libraries are wrappers around Date. It works well enough for 99% of cases.

    • to3m 6 years ago

      https://js-joda.github.io/js-joda/cheat-sheet.html

      EDIT: My precious internet points! ;) - wait, is this not a page of examples, as linked to from the GitHub page?

      • jazoom 6 years ago

        I think you might be downvoted because you plastered a link with no explanation. It doesn't actually address my concern, which was that when I was reading the documentation I did not see any examples.

    • cel1ne 6 years ago

      Date-handling should work in 100% of cases.

      You can built syntactic sugar around js-joda too.

      I develop Java/kotlin as well, so I'm used to the API. It feels verbose, but it makes a lot of sense. Date-handling is complex, a library shouldn't hide that.

      • jazoom 6 years ago

        That's not what I meant by "works". I meant works for the use case. Moment has worked 100% for me whenever I used it. It's API is simple and does what it says.

  • tobyhinloopen 6 years ago

    Oh this one looks nice! Documentation looks like someone actually thought about it