You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dayjs Calendar方法返回格式异常问题求助

Fixing day.js Calendar Method Returning 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_at in UTC is 2020-12-23T07:28:19Z, which becomes 2020-12-23T10:28:19+03:00 in Novosibirsk.
  • If your local timezone is UTC, the current "now" (12/30) is 2020-12-30T00:00:00Z, but in Novosibirsk it's 2020-12-30T03:00:00+03:00. The interval between the two dates in Novosibirsk is exactly 7 days—perfect for lastWeek—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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:23:12