Dayjs Calendar方法返回格式异常问题求助
sameElse Instead of lastWeek Hey there! I see you're migrating from moment.js to day.js and hitting a snag with the calendar() method. Let's break down what's going wrong and how to fix it.
The Root Cause
Your code converts the target date (created_at) to the Asia/Novosibirsk timezone, but the reference "now" time used by calendar() is still stuck in your local timezone (or UTC, if unconfigured). This timezone mismatch throws off the logic that categorizes dates into lastWeek, sameDay, etc.
For context:
created_atin UTC is2020-12-23T07:28:19Z, which becomes2020-12-23T10:28:19+03:00in Novosibirsk.- If your local timezone is UTC, the current "now" (12/30) is
2020-12-30T00:00:00Z, but in Novosibirsk it's2020-12-30T03:00:00+03:00. The interval between the two dates in Novosibirsk is exactly 7 days—perfect forlastWeek—but comparing a Novosibirsk date to a UTC "now" confuses day.js's logic.
Step-by-Step Fix
First, make sure you've installed and imported all required day.js plugins (these aren't included in the core library):
import dayjs from 'dayjs'; import utc from 'dayjs/plugin/utc'; import timezone from 'dayjs/plugin/timezone'; import calendar from 'dayjs/plugin/calendar'; dayjs.extend(utc); dayjs.extend(timezone); dayjs.extend(calendar);
Option 1: Explicitly Pass a Timezone-Aligned "Now"
Convert your current time to the target timezone and use it as the reference for calendar():
const created_at = '2020-12-23T07:28:19Z'; const tzIdentifier = 'Asia/Novosibirsk'; const calendar_options = { sameDay: '[Today at] h:mm A', nextDay: '[Tomorrow at] h:mm A', nextWeek: 'dddd [at] h:mm A', lastDay: '[Yesterday at] h:mm A', lastWeek: '[Last] dddd [at] h:mm A', sameElse: 'DD/MM/YYYY' }; // Get current time converted to the target timezone const nowInTargetTz = dayjs().tz(tzIdentifier); // Convert created_at to UTC first, then target timezone, then compare const formattedDate = dayjs.utc(created_at).tz(tzIdentifier).calendar(nowInTargetTz, calendar_options); console.log(formattedDate); // Returns "Last Wednesday at 10:28 AM" (correct lastWeek format)
Option 2: Set a Global Default Timezone
If your whole project uses Asia/Novosibirsk, set it as the default so all date comparisons auto-align:
// Set default timezone globally dayjs.tz.setDefault('Asia/Novosibirsk'); const created_at = '2020-12-23T07:28:19Z'; const calendar_options = { /* same as above */ }; const formattedDate = dayjs(created_at).calendar(null, calendar_options); console.log(formattedDate); // Also returns the correct lastWeek format
Why This Works
By aligning both the target date and reference "now" to the same timezone, day.js can accurately calculate the interval between them and apply the right calendar() rule. Unlike moment.js (which auto-uses the date instance's timezone for comparisons), day.js needs explicit alignment unless you set a global default.
内容的提问来源于stack exchange,提问作者Nikita

