Skip to content

Commit 66352de

Browse files
authored
fix: Fix daily frequency compensating for DST (#96)
The date transitioning from Standard Time to DST "has" 25 hours in the day. This fixes genNextDay to use `date-fns` so the correct day is returned instead of naively adding 24 hours to the date. Fixes #95
1 parent ddc07b5 commit 66352de

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

lib/utils.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const { readdir, stat, unlink, symlink, lstat, readlink } = require('fs/promises')
44
const { dirname, join } = require('path')
5-
const { format } = require('date-fns')
5+
const { format, addDays, addHours } = require('date-fns')
66

77
function parseSize (size) {
88
let multiplier = 1024 ** 2
@@ -53,11 +53,11 @@ function validateLimitOptions (limit) {
5353
}
5454

5555
function getNextDay (start) {
56-
return new Date(start + 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0)
56+
return addDays(new Date(start), 1).setHours(0, 0, 0, 0)
5757
}
5858

5959
function getNextHour (start) {
60-
return new Date(start + 60 * 60 * 1000).setMinutes(0, 0, 0)
60+
return addHours(new Date(start), 1).setMinutes(0, 0, 0)
6161
}
6262

6363
function getNextCustom (frequency) {

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
},
2929
"devDependencies": {
3030
"husky": "^9.0.11",
31+
"mockdate": "^3.0.5",
3132
"pino": "^9.2.0",
3233
"snazzy": "^9.0.0",
3334
"standard": "^17.0.0-2",

test/lib/utils.test.js

+61
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const { writeFile, rm, stat, readlink, symlink } = require('fs/promises')
55
const { join } = require('path')
66
const { test } = require('tap')
77
const { format } = require('date-fns')
8+
const MockDate = require('mockdate')
89

910
const {
1011
buildFileName,
@@ -69,6 +70,66 @@ test('getNext()', async ({ same }) => {
6970
same(getNext(custom), Date.now() + custom, 'supports custom frequency and does not return start')
7071
})
7172

73+
test('getNext() on dates transitioning from DST to Standard Time', async ({ same }) => {
74+
// on these days the time rolls back 1 hour so there "are" 25 hours in the day
75+
// genNext() should account for variable number of hours in the day
76+
77+
// test two different timezones
78+
const data = [
79+
{
80+
tz: 'Europe/Berlin',
81+
mockDate: '27 Oct 2024 00:00:00 GMT+0100'
82+
},
83+
{
84+
tz: 'America/New_York',
85+
mockDate: '03 Nov 2024 00:00:00 GMT-0500'
86+
}
87+
]
88+
89+
for (const d of data) {
90+
MockDate.set(d.mockDate)
91+
process.env.TZ = d.tz
92+
const today = new Date()
93+
94+
same(getNext('daily'), startOfDay(addDays(today, 1)).getTime(), 'supports daily frequency')
95+
same(getNext('hourly'), startOfHour(addHours(today, 1)).getTime(), 'supports hourly frequency')
96+
const custom = 3000
97+
same(getNext(custom), Date.now() + custom, 'supports custom frequency and does not return start')
98+
MockDate.reset()
99+
process.env.TZ = undefined
100+
}
101+
})
102+
103+
test('getNext() on dates transitioning from Standard Time to DST', async ({ same }) => {
104+
// on these days the time rolls forward 1 hour so there "are" 23 hours in the day
105+
// genNext() should account for variable number of hours in the day
106+
107+
// test two different timezones
108+
const data = [
109+
{
110+
tz: 'Europe/Berlin',
111+
mockDate: '31 March 2024 01:00:00 GMT+0100'
112+
},
113+
{
114+
tz: 'America/New_York',
115+
mockDate: '10 Nov 2024 01:00:00 GMT-0500'
116+
}
117+
]
118+
119+
for (const d of data) {
120+
MockDate.set(d.mockDate)
121+
process.env.TZ = d.tz
122+
const today = new Date()
123+
124+
same(getNext('daily'), startOfDay(addDays(today, 1)).getTime(), 'supports daily frequency')
125+
same(getNext('hourly'), startOfHour(addHours(today, 1)).getTime(), 'supports hourly frequency')
126+
const custom = 3000
127+
same(getNext(custom), Date.now() + custom, 'supports custom frequency and does not return start')
128+
MockDate.reset()
129+
process.env.TZ = undefined
130+
}
131+
})
132+
72133
test('getFileName()', async ({ equal, throws }) => {
73134
const strFunc = () => 'my-func'
74135
throws(getFileName, 'throws on empty input')

0 commit comments

Comments
 (0)