⏱ A library for working with dates and times in JS

Overview

Luxon

MIT License Build Status NPM version Coverage Status Doc coverage PRs welcome

Luxon is a library for working with dates and times in JavaScript.

DateTime.now().setZone("America/New_York").minus({ weeks: 1 }).endOf("day").toISO();

Features

  • DateTime, Duration, and Interval types.
  • Immutable, chainable, unambiguous API.
  • Parsing and formatting for common and custom formats.
  • Native time zone and Intl support (no locale or tz files).

Download/install

Download/install instructions

Documentation

Development

See contributing.

Phasers to stun

Comments
  • Use Flow or Typescript

    Use Flow or Typescript

    Hi,

    Is it possible to incorporate typescript definition files into this fantastic project or maintain typescript definition files in @types? I am sure this would definitely benefit the whole community.

    issue: enhancement help wanted up for grabs 
    opened by Mocha-- 27
  • toFormat() does not work with i18n and fails on Node.js

    toFormat() does not work with i18n and fails on Node.js

    Trying in Node.js with the following (this is the documentation example): DateTime.fromISO('2014-08-06T13:07:04.054').setLocale('fr').toFormat('yyyy LLL dd'); I get the result: "null Aug null".

    The Node app runs on a server in UK (which has not brexited yet ;-) and rather than the French "aou." for month I get the English "Aug". Moreover day (dd) and year (yyyy) miserably fail ;-(

    Luckily, the toLocalString works. But I need to handle various user format.

    See screen shot.

    screenshot_2018-10-12 15 51 47_yl7br8 issue: troubleshooting 
    opened by PierreKauffmann 23
  • startOf('week') is not respecting locale setting

    startOf('week') is not respecting locale setting

    While most countries in the world assume the week starts on Monday, US, Canada, and Australia consider Sunday as the first day of the week. It seems that luxon hard-coded the start of week as Monday.

    // prints "2018-11-19T00:00:00.000-08:00"
    console.log(DateTime.fromISO('2018-11-22T10:00', {zone: 'America/Los_Angeles'}.startOf('week').toISO());
    

    Note that moment does actually respect the locale setting

    // prints "2018-11-18T08:00:00.000Z"
    console.log(moment.tz('2018-11-22T10:00', "America/Los_Angeles").startOf('week').toISOString());
    
    opened by mars-lan 21
  • Can Luxon retrieve a list of all valid timezone names?

    Can Luxon retrieve a list of all valid timezone names?

    I'm trying to implement functionality in my app that allows the user to enter a local time, and then assign a custom timezone identifier for a different timezone (e.g. Asia/Ho_Chi_Minh).

    I'm doing this so that due dates/times can be entered relative to a remote location without the user having to manually calculate what the local time of their current location would be at that instant (and maybe get it wrong due to DST changes, etc.).

    Luxon lets me retrieve the timezone identifier for the current location:

    DateTime.local().zoneName
    

    but I'm having a hard time establishing whether or not Luxon will allow me to retrieve an entire list of all valid identifiers. There's no obvious API call in the docs for this, and I'm mindful that as Luxon calls on the browser, it most likely doesn't maintain its own list internally.

    Is there a means of achieving this through Luxon? If not, are there any alternative recommendations for this need?

    opened by Lx 21
  • Making Luxon smaller

    Making Luxon smaller

    The Chrome debugger tells me that moment.min.js was 50.2 KB and that luxon.min.js is 90.2 KB. Is there anything we can do to make Luxon smaller for client-side usage?

    I'm not primarily a JS developer, but it looks like Luxon is implemented using ES6/ES2015 modules? And so users might be able to use tree shaking to pull in only the parts of Luxon that they need? This could be helpful to document is so

    date-fns is written in a function-per-file style, which makes it much easier to pull in just what you need and to end up with a much smaller binary. It also makes it easier to use with bundlers like rollup. Is there any chance that Luxon might consider a more functional style like date-fns?

    needs thought 
    opened by benmccann 20
  • Not working with ESM on Node 10

    Not working with ESM on Node 10

    Hey, any chance to have luxon work with Node ESM modules?

    import { DateTime } from 'luxon';
               ^^^^^^^^
    SyntaxError: The requested module 'luxon' does not provide an export named 'DateTime'
    at ModuleJob._instantiate (internal/modules/esm/module_job.js:89:21)
    
    help wanted issue: install/load 
    opened by damianobarbati 18
  • 2.0 plans

    2.0 plans

    I want to make a number of breaking changes in 2.0:

    1. Remove DateTime#until. That will let us strip out the DateTime -> Interval dependency and help with tree shaking.
    2. Move toFormat() and fromFormat to their own top-level class (i.e. DateTimeFormat.fromFormat() returns a DateTime)
    3. Move the presets to their own namespace to help with tree-shaking
    4. Move all of the IE-supporting code into another module
    5. Collapse all of the error types into one with different messages

    I could use some feedback, especially on items 2 and 4.

    future plans 
    opened by icambron 18
  • DateTime.toFormat('ZZZZ') not showing expected output

    DateTime.toFormat('ZZZZ') not showing expected output

    According to the docs, when the 'ZZZZ' token is passed in the format string, the abbreviated named offset string should be displayed in the output string. However, the timezone offset from GMT is being displayed instead.

    Code snippet to test the issue:

    DateTime.fromISO("2019-05-03T10:59:22Z")
    .setZone("America/Los_Angeles")
    .toFormat('dd-MMM-yy hh:mm:ss ZZZZ');
    

    Expected Output:

    03-May-19 03:59:22 PDT
    

    Actual Output:

    03-May-19 03:59:22 GMT-7
    

    Package Version: ^1.13.0

    Environments: [email protected], Chrome

    issue: troubleshooting 
    opened by eragon512 16
  • 1.11.4 fix which returns default timezone if set for the alias 'local' breaks everything

    1.11.4 fix which returns default timezone if set for the alias 'local' breaks everything

    Hello.

    Until the recent update to 1.11.4 using local time zone as a string explicitly set the zone to the browser default. While this was unexpected initially, we worked around it as follows:

    // Set default time zone for project:
    Settings.defaultZoneName = timezone || 'local';
    
    // To interpret server side dates given in ISO:
    const zonedDate = DateTime.fromISO(date); // Interprets it as the project timezone
    
    // Show on the UI: Must be scoped to browser timezone so as to show it in terms of the local time
    // which may be different from the project timezone (Ex: A user in Japan selecting shift timings in a 
    // date input for a project in India - The user in Japan must be able to select times (say 8am to 3pm) 
    // in his/her worldview without having to do conversions
    const displayDate = zoneDate.setZone('local', {keepLocalTime: true});
    
    // Parse input from the date-picker in browser zone, convert to project timezone, convert to ISO for server
    const utc = DateTime
                                    .fromJSDate(date, {zone: 'local'})
                                     // Get project time zone by checking the zone of .a new DateTime object
                                    .setZone(DateTime.local().zoneName, {keepLocalTime: true})
                                    .setZone('utc')
                                    .toMillis()
    
    

    Now obviously this has stopped working. I have to admit that the new behaviour should be the expected behaviour. I was initially surprised by the older behaviour and had to code around it. Now this fix is breaking all our code 😆 . While this is something which can be fixed on our end, I feel there is a legitimate need to be able to quick access the browser default.

    Perhaps we can introduce a new alias like local such as system? Or is there a better solution I'm not seeing? (I'd like to avoid the use of the timeZoneOffset from the native date object although that is one feasible solution)

    opened by cravindra 16
  • Interval#splitBy can cause infinite loop

    Interval#splitBy can cause infinite loop

    Interval#splitBy hangs the process with an infinite loop if duration argument is not valid.

    Repro: https://codesandbox.io/s/n469pm30o4 (WARNING: this will hang the tab).

    const dateStart = DateTime.local().startOf("day");
    const dateEnd = dateStart.plus({ days: 6 }).endOf("day");
    const dates = Interval.fromDateTimes(dateStart, dateEnd).splitBy(DateTime.local());
    
    issue: bug good first contribution 
    opened by vlad-zhukov 16
  • Moar speed

    Moar speed

    I would love some help with perf testing and fixes. I suspect there are a lot of CPU cycles to squeeze out of this thing, especially at instance creation.

    up for grabs issue: performance 
    opened by icambron 16
  • Inconsistent DateTime format when using toLocaleString

    Inconsistent DateTime format when using toLocaleString

    I don't know if this is related to something on my MacBook, but for some reason, my tests started failing with this:

    const timestamp = "2022-05-11T23:23:00-07:00";  // Example timestamp string
    DateTime.fromISO(timestamp, { zone: 'America/Los_Angeles' }).toLocaleString(DateTime.DATETIME_FULL);
    

    On any other machine, this is the sample formatted output, but should be correct according to the documentation: May 12, 2022, 7:00 AM PDT

    On my Macbook, I would get this instead: May 12, 2022 at 7:00 AM PDT

    • OS: MacOS 13.0.1
    • node.js version: 19.1.0
    • Luxon version: 3.1.0
    • Timezone: America/Los_Angeles
    opened by bliu13 9
  • luxon.DateTime.parseFormatForOpts() returns wrong format token for

    luxon.DateTime.parseFormatForOpts() returns wrong format token for "numeric" year

    Describe the bug Calling luxon.DateTime.parseFormatForOpts({year: 'numeric'}, {locale: 'en-US'}); should produce 'yyyy' according to the token format definition: https://moment.github.io/luxon/#/formatting?id=table-of-tokens But it produces 'yyyyy', i.e. on 'y' to much. The generated token is important for a postprocessing to be passed to a 3rd party UI component To Reproduce

    // passing the locale is irrelevant by the way
    console.assert(luxon.DateTime.parseFormatForOpts({year: 'numeric'}, {locale: 'en-US'}) === 'yyyy');
    // Assertion failed
    

    Actual vs Expected behavior

    // passing the locale is irrelevant by the way
    console.assert(luxon.DateTime.parseFormatForOpts({year: 'numeric'}, {locale: 'en-US'}) === 'yyyy');
    // Assertion passed
    

    Desktop (please complete the following information):

    • OS: Windows 10, 64 bit
    • Browser: Chrome 107
    • Luxon version 3.1.0 (also tested with luxon available on dev console on luxon website)
    • Your timezone [e.g. "Germany/Berlin"]

    Additional context nothing

    opened by Rondomat 0
  • Feature request: Add 'T' character if needed to ISO-8601 strings

    Feature request: Add 'T' character if needed to ISO-8601 strings

    When trying to use DateTime.fromISO for an ISO-8601 string that contains a space instead of a T character (aka, instead of 2022-11-14T19:56:20, a string like 2022-11-14 19:56:20, Luxon should handle this alternative format or should provide an option to allow the T to be added.

    opened by jamesexplo 4
  • moment.github.io/luxon website not loading

    moment.github.io/luxon website not loading

    Describe the bug The page is not loading, it stucks at a Loading... message.

    To Reproduce Go to https://moment.github.io/luxon/ and see

    Actual vs Expected behavior I expect it to load the docs

    Desktop (please complete the following information):

    • OS: [e.g. iOS]: MacOS
    • Browser [e.g. Chrome 84, safari 14.0] Latest Chrome and Firefox

    Additional context Loading failed for the