iamkun / iamkun/dayjs

When using .add(1,'month') month becomes correct but year becomes previous year. 2023-01-01 -> +1 month -> 2022-02-01

Open
#2,810 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
48.7k
Forks
2.5k
PR merge metrics
No merged PRs in 30d

Description

**Describe the Bug**
When using `dayjs.utc(...).tz('utc').startOf('day')` and then adding a month (`.add(1, 'month').startOf('month')`), the resulting date sometimes jumps back by a year if the start date is January 1st. This only happens in the browser and not in Node.js. It also seems to only happen when you have a utc instances and call .tz('utc') on it.

**Expected Behavior**
The date should stay in the correct year without rolling back.

**Steps to Reproduce**
1. Initialize the date with `dayjs.utc('2023-01-01').tz('utc').startOf('day')`.
2. Add one month with `.add(1, 'month').startOf('month')`.
3. Note how the year can shift back.

**Demo**
[[StackBlitz Link](https://stackblitz.com/edit/dayjs-playground-pcr9xsfg?file=index.js)](https://stackblitz.com/edit/dayjs-playground-pcr9xsfg?file=index.js)

**Environment**
- Day.js Version: 1.11.13
- OS: Tested on mac os
- Browser: Chrome
- Time Zone: Europe/Oslo

Code from stackblitz:

````
import './style.css';
import dayjs from 'dayjs';
import timezone from 'dayjs/plugin/timezone.js';
import utc from 'dayjs/plugin/utc.js';
dayjs.extend(utc);
dayjs.extend(timezone);

const doDateStuff = (start = '2023-01-01') => {
const startDate = dayjs.utc(start).tz('utc');

let current = startDate;
const dates = [];

for (let i = 0; i < 10; i++) {
dates.push(current.format());
current = current.add(1, 'month').startOf('month');
}

return {
startDate: startDate.format(),
dates,
};
};

const doDateStuffBroken = (start = '2023-01-01') => {
const startDate = dayjs.utc(start).tz('utc').startOf('day'); // broken because of startOf it seems

let current = startDate;
const dates = [];

for (let i = 0; i < 10; i++) {
dates.push(current);
current = current.add(1, 'month').startOf('month');
}

return {
year: startDate.year(),
startDate: startDate.format(),
dates,
};
};

const datesCalc = doDateStuff();
const datesCalcBroken = doDateStuffBroken();

// Write Javascript code!
const appDiv = document.getElementById('app');
appDiv.innerHTML = `

Dates working

${datesCalc.dates
.map((d) => {
return ``;
})
.join('')}



DateTime string should be same year



${d}

Dates Broken - Skips back a year only if jan 1 and using startOf

${datesCalcBroken.dates
.map((d) => {
return ``;
})
.join('')}



DateTime string should be same year



${d}

`;

Contributor guide

Open the contributing guide

Research direction

Start with the StackBlitz index.js reproduction and compare the two date-building paths using the utc and timezone plugins. Run it in Chrome and Node.js with the January 1, 2023 input, then verify that repeated add(1, 'month').startOf('month') calls preserve the year.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
web-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.