Search code examples
luxon

Displaying time relative to a given using luxon library


Does luxon support feature for Displaying time relative to a given?

Moment has "Calendar time" feature:

https://momentjs.com/docs/#/displaying/calendar-time/

moment().calendar(null, {
   sameDay: '[Today]',
   nextDay: '[Tomorrow]',
   nextWeek: 'dddd',
   lastDay: '[Yesterday]',
   lastWeek: '[Last] dddd',
   sameElse: 'DD/MM/YYYY'
});

Could I achieve same using luxon?


Solution

  • From version 1.9.0 you can use toRelativeCalendar:

    Returns a string representation this date relative to today, such as "yesterday" or "next month" platform supports Intl.RelativeDateFormat.

    const DateTime = luxon.DateTime;
    
    const now = DateTime.local();
    // Some test values
    [ now,
      now.plus({days: 1}),
      now.plus({days: 4}),
      now.minus({days: 1}),
      now.minus({days: 4}),
      now.minus({days: 20}),
    ].forEach((k) => {
      console.log( k.toRelativeCalendar() );
    });
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/global/luxon.js"></script>


    Before version 1.9.0, there was no calendar() equivalent in Luxon.

    The For Moment users manual page stated in the DateTime method equivalence => Output => Humanization section:

    Luxon doesn't support these, and won't until the Relative Time Format proposal lands in browsers.

    Operation       | Moment     | Luxon
    ---------------------------------------------------------------------------------------
    "Calendar time" | calendar() | None (before 1.9.0) / toRelativeCalendar() (after 1.9.0)
    

    If you need, you can write something by yourself, here a custom function example that has a similar output of moment's calendar():

    const DateTime = luxon.DateTime;
    
    function getCalendarFormat(myDateTime, now) {
      var diff = myDateTime.diff(now.startOf("day"), 'days').as('days');
      return diff < -6 ? 'sameElse' :
        diff < -1 ? 'lastWeek' :
        diff < 0 ? 'lastDay' :
        diff < 1 ? 'sameDay' :
        diff < 2 ? 'nextDay' :
        diff < 7 ? 'nextWeek' : 'sameElse';
    }
    
    function myCalendar(dt1, dt2, obj){
      const format = getCalendarFormat(dt1, dt2) || 'sameElse';
      return dt1.toFormat(obj[format]);
    }
    
    const now = DateTime.local();
    const fmtObj = {
       sameDay: "'Today'",
       nextDay: "'Tomorrow'",
       nextWeek: 'EEEE',
       lastDay: "'Yesterday'",
       lastWeek: "'Last' EEEE",
       sameElse: 'dd/MM/yyyy'
    };
    
    // Some test values
    [ now,
      now.plus({days: 1}),
      now.plus({days: 4}),
      now.minus({days: 1}),
      now.minus({days: 4}),
      now.minus({days: 20}),
    ].forEach((k) => {
      console.log( myCalendar(now, k, fmtObj) );
    });
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/global/luxon.js"></script>

    This code roughly inspired from moment code, it can be definitely improved.