Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calendar format returns wrong date #1226

Open
DenisaHalmaghi opened this issue Nov 16, 2020 · 7 comments
Open

Calendar format returns wrong date #1226

DenisaHalmaghi opened this issue Nov 16, 2020 · 7 comments

Comments

@DenisaHalmaghi
Copy link

Hello!

I have the following snippet:

import calendar from 'dayjs/plugin/calendar';
dayjs.extend(calendar);

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

The problems , in my opinion, are :

  • if the date falls under the sameElse category i get the date of today ( since today is 16/11/2020, i get 16/11/2020 for all dates that fall under sameElse)
  • all dates under next and last are inverted - meaning if i choose 17/11/2020, i get yesterday, and i if choose 15/11/2020, i get tomorrow
  • also, for dates such as 18/11/2020,19/11/2020 i get last Monday instead of Wednesday or Thursday, and for dates such as 14/11/2020 i get Monday instead of last Sunday

If I'm missing something from the documentation, please let me know, but in my opinion this isn't the right behaviour for this function.

Thank you for your time!

@DenisaHalmaghi DenisaHalmaghi changed the title Calendar format returns format for today Calendar format returns wrong date Nov 16, 2020
@bobbyconnolly
Copy link

bobbyconnolly commented Jan 5, 2021

I had the same issue. As a workaround, I test for diff < 6 days

if (
    Math.abs(
        dayjs().diff(file.lastModified, "day")
    ) < 6
) {
    console.log(
        "lm1",
        dayjs().calendar(dayjs(file.lastModified))
    );
} else {
    console.log(
        "lm2",
        dayjs(file.lastModified).format(
            "YYYY-MM-DD"
        )
    );
}

@bobbyconnolly
Copy link

bobbyconnolly commented Jan 5, 2021

Here is a more complete workaround that overrides calendar() with the fix:

import "dayjs/locale/fr";
import dayjs from "dayjs";
import calendar from "dayjs/plugin/calendar";
import updateLocale from "dayjs/plugin/updateLocale";

dayjs.extend(calendar);
dayjs.extend(updateLocale);

dayjs.updateLocale("fr", {
    calendar: {
        sameDay: "[aujourd'hui à] H:mm",
        nextDay: "[demain à] H:mm",
        nextWeek: "dddd [prochain]",
        lastDay: "[hier à] H:mm",
        lastWeek: "dddd [dernier]",
        sameElse: "YYYY-MM-DD",
    },
});

const defaultCalendar = dayjs.prototype.calendar;

dayjs.prototype.calendar = function calendar(
    referenceTime?: string | number | dayjs.Dayjs | Date | undefined,
    formats?: object | undefined
) {
    if (
        dayjs().diff(dayjs(referenceTime), "day") < -6 ||
        dayjs().diff(dayjs(referenceTime), "day") > 7
    ) {
        return dayjs(referenceTime).format("YYYY-MM-DD");
    } else {
        return defaultCalendar.call(dayjs(referenceTime), [dayjs(), formats]);
    }
};

export default dayjs;

@borie88
Copy link

borie88 commented Jan 28, 2021

We could even extend that more to take into account whether or not our dates belong to the same week, which seems more accurate.

lastWeek should mean the week before (not more than one day before), and nextWeek should mean the week after (not anytime between the day after tomorrow and 6 days from now).

So we would need to add a sameWeek as well. Here is some rudimentary rewrite of the calendar plugin. The only issue is it now depends on the weekOfYear plugin being installed (because this.diff(date, 'w') doesn't take the actual week of year into account):

export default (o, c, d) => {
  const LT = 'h:mm A'
  const L = 'MM/DD/YYYY'
  const calendarFormat = {
    lastDay: `[Yesterday at] ${LT}`,
    sameDay: `[Today at] ${LT}`,
    nextDay: `[Tomorrow at] ${LT}`,
    sameWeek: `dddd [at] ${LT}`,
    nextWeek: `[Next] dddd [at] ${LT}`,
    lastWeek: `[Last] dddd [at] ${LT}`,
    sameElse: L
  }
  const proto = c.prototype
  proto.calendar = function (referenceTime, formats) {
    const format = formats || this.$locale().calendar || calendarFormat
    const referenceStartOfDay = d(referenceTime || undefined).startOf('d')
    const diff = this.diff(referenceStartOfDay, 'd', true)
    const weekDiff = this.week() - referenceStartOfDay.week()
    const sameElse = 'sameElse'
    /* eslint-disable no-nested-ternary */
    const retVal = weekDiff < -1 || weekDiff > 1 ? sameElse :
      diff < -1 ? weekDiff === 0 ? 'sameWeek' : 'lastWeek' :
        diff < 0 ? 'lastDay' :
          diff < 1 ? 'sameDay' :
            diff < 2 ? 'nextDay' :
              weekDiff === 0 ? 'sameWeek' : 'nextWeek'
    /* eslint-enable no-nested-ternary */
    const currentFormat = format[retVal] || calendarFormat[retVal]
    if (typeof currentFormat === 'function') {
      return currentFormat.call(this, d())
    }
    return this.format(currentFormat)
  }
}

@leslie-heinzen
Copy link

Any update on this? I'm patching the plugin for now similar to what @borie88 helpfully suggested above. Just curious if this will make it into the library.

Here's a reproduction if anyone else encountering this issue wants to look: https://codesandbox.io/s/billowing-dream-7obed

@TeChn4K
Copy link

TeChn4K commented Apr 21, 2021

I solved this issue by switching the two dates :

// wrong
dayjs().calendar(dayjs(date))

// good
dayjs(date).calendar(dayjs())

// better!
dayjs(date).calendar()

I don't know if the issue is about the documentation or the calendar plugin.

@kadiraydinli
Copy link

dayjs.extend(calendar)

dayjs(date).calendar(undefined, {
  sameDay: '[Today at] h:mm A',
  lastDay: '[Yesterday at] h:mm A',
  lastWeek: '[Last] dddd [at] h:mm A',
  sameElse: 'DD/MM/YYYY'
})

That's how it worked for me.

@loucadufault
Copy link

I solved this issue by switching the two dates :

// wrong
dayjs().calendar(dayjs(date))

// good
dayjs(date).calendar(dayjs())

// better!
dayjs(date).calendar()

I don't know if the issue is about the documentation or the calendar plugin.

Seems odd that both mentions of Calendar Time in the documentation use the construction:

dayjs().calendar(dayjs('2008-01-01'))

See:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants