diff --git a/lib/datasource/npm/get.ts b/lib/datasource/npm/get.ts index 642b5c55a587baab366cfc39b37ced0f18697a11..9a567cd0fd8b9d0464b3e4d0d29d57167d5b26f3 100644 --- a/lib/datasource/npm/get.ts +++ b/lib/datasource/npm/get.ts @@ -2,7 +2,7 @@ import { OutgoingHttpHeaders } from 'http'; import url from 'url'; import is from '@sindresorhus/is'; import delay from 'delay'; -import moment from 'moment'; +import { DateTime } from 'luxon'; import registryAuthToken from 'registry-auth-token'; import getRegistryUrl from 'registry-auth-token/registry-url'; import { logger } from '../../logger'; @@ -218,7 +218,12 @@ export async function getDependency( if (res.time?.[version]) { release.releaseTimestamp = res.time[version]; release.canBeUnpublished = - moment().diff(moment(release.releaseTimestamp), 'days') === 0; + DateTime.local() + .startOf('day') + .diff( + DateTime.fromISO(release.releaseTimestamp).startOf('day'), + 'days' + ).days === 0; } if (res.versions[version].deprecated) { release.isDeprecated = true; diff --git a/lib/datasource/npm/index.spec.ts b/lib/datasource/npm/index.spec.ts index 00dfde3e164bcef47af58ccbea0c26e7ce7b5cc6..2c1633deca9afa20bc842cee001025cbb0b9a13a 100644 --- a/lib/datasource/npm/index.spec.ts +++ b/lib/datasource/npm/index.spec.ts @@ -1,4 +1,4 @@ -import moment from 'moment'; +import { DateTime } from 'luxon'; import nock from 'nock'; import _registryAuthToken from 'registry-auth-token'; import { getPkgReleases } from '..'; @@ -171,7 +171,7 @@ describe(getName(__filename), () => { expect(getRelease(res, '0.0.2').canBeUnpublished).toBeUndefined(); }); it('should return canBeUnpublished=true', async () => { - npmResponse.time['0.0.2'] = moment().subtract(6, 'hours').format(); + npmResponse.time['0.0.2'] = DateTime.local().minus({ hours: 6 }).toISO(); nock('https://registry.npmjs.org').get('/foobar').reply(200, npmResponse); const res = await getPkgReleases({ datasource, depName: 'foobar' }); expect(getRelease(res, '0.0.1').canBeUnpublished).toBe(false); diff --git a/lib/workers/branch/schedule.ts b/lib/workers/branch/schedule.ts index afadff754360f2182f2c7a6e8fab0ddc8b4a0c44..009f76a608eb95b71d682ca3393bf21b4d09c062 100644 --- a/lib/workers/branch/schedule.ts +++ b/lib/workers/branch/schedule.ts @@ -1,6 +1,6 @@ import later from '@breejs/later'; import is from '@sindresorhus/is'; -import moment from 'moment-timezone'; +import { DateTime } from 'luxon'; import { RenovateConfig } from '../../config'; import { logger } from '../../logger'; @@ -16,7 +16,7 @@ function fixShortHours(input: string): string { export function hasValidTimezone( timezone: string ): [boolean] | [boolean, string] { - if (!moment.tz.zone(timezone)) { + if (!DateTime.local().setZone(timezone).isValid) { return [false, `Invalid schedule: Unsupported timezone ${timezone}`]; } return [true]; @@ -92,8 +92,8 @@ export function isScheduledNow(config: RenovateConfig): boolean { logger.warn(errorMessage); return true; } - let now = moment(); - logger.trace(`now=${now.format()}`); + let now = DateTime.local(); + logger.trace(`now=${now.toISO()}`); // Adjust the time if repo is in a different timezone to renovate if (config.timezone) { logger.debug({ timezone: config.timezone }, 'Found timezone'); @@ -103,15 +103,15 @@ export function isScheduledNow(config: RenovateConfig): boolean { return true; } logger.debug('Adjusting now for timezone'); - now = now.tz(config.timezone); - logger.trace(`now=${now.format()}`); + now = now.setZone(config.timezone); + logger.trace(`now=${now.toISO()}`); } - // Get today in text form, e.g. "Monday"; - const currentDay = now.format('dddd'); + const currentDay = now.weekday; logger.trace(`currentDay=${currentDay}`); // Get the number of seconds since midnight - const currentSeconds = - now.hours() * 3600 + now.minutes() * 60 + now.seconds(); + const currentSeconds = now + .startOf('second') + .diff(now.startOf('day'), 'seconds').seconds; logger.trace(`currentSeconds=${currentSeconds}`); // Support a single string but massage to array for processing logger.debug(`Checking ${configSchedule.length} schedule(s)`); @@ -124,7 +124,7 @@ export function isScheduledNow(config: RenovateConfig): boolean { return parsedSchedule.schedules.some((schedule) => { // Check if months are defined if (schedule.M) { - const currentMonth = parseInt(now.format('M'), 10); + const currentMonth = now.month; if (!schedule.M.includes(currentMonth)) { logger.debug( `Does not match schedule because ${currentMonth} is not in ${String( @@ -136,19 +136,10 @@ export function isScheduledNow(config: RenovateConfig): boolean { } // Check if days are defined if (schedule.d) { - // We need to compare text instead of numbers because - // 'moment' adjusts day of week for locale while 'later' does not - // later days run from 1..7 - const dowMap = [ - null, - 'Sunday', - 'Monday', - 'Tuesday', - 'Wednesday', - 'Thursday', - 'Friday', - 'Saturday', - ]; + // We need to map because 'luxon' uses monday as first day + // and later uses sundays as first day of week + // http://bunkat.github.io/later/time-periods.html#day-of-week + const dowMap = [6, 7, 1, 2, 3, 4, 5, 6]; const scheduledDays = schedule.d.map((day) => dowMap[day]); logger.trace({ scheduledDays }, `scheduledDays`); if (!scheduledDays.includes(currentDay)) { @@ -162,8 +153,7 @@ export function isScheduledNow(config: RenovateConfig): boolean { } if (schedule.D) { logger.debug({ schedule_D: schedule.D }, `schedule.D`); - // moment outputs as string but later outputs as integer - const currentDayOfMonth = parseInt(now.format('D'), 10); + const currentDayOfMonth = now.day; if (!schedule.D.includes(currentDayOfMonth)) { return false; } @@ -189,7 +179,7 @@ export function isScheduledNow(config: RenovateConfig): boolean { } } // Check for week of year - if (schedule.wy && !schedule.wy.includes(now.week())) { + if (schedule.wy && !schedule.wy.includes(now.weekNumber)) { return false; } logger.debug(`Matches schedule ${scheduleText}`); diff --git a/lib/workers/repository/process/limits.spec.ts b/lib/workers/repository/process/limits.spec.ts index ae31e9a46d1cb96bd301abda1531efa6089a9d40..58f0e479c3684425b2ad8a3b61f9f1a2ca143094 100644 --- a/lib/workers/repository/process/limits.spec.ts +++ b/lib/workers/repository/process/limits.spec.ts @@ -1,4 +1,4 @@ -import moment from 'moment'; +import { DateTime } from 'luxon'; import { RenovateConfig, getConfig, platform } from '../../../../test/util'; import { PrState } from '../../../types'; import { BranchConfig } from '../../common'; @@ -16,7 +16,7 @@ describe('workers/repository/process/limits', () => { config.prHourlyLimit = 2; platform.getPrList.mockResolvedValueOnce([ { - createdAt: moment().toISOString(), + createdAt: DateTime.local().toISO(), sourceBranch: null, title: null, state: null, diff --git a/lib/workers/repository/process/limits.ts b/lib/workers/repository/process/limits.ts index 088c84752d6be574aac349f9d71eff3cb67f8f3d..7a434c5bf7ed9317181ec13da6095339c1e94172 100644 --- a/lib/workers/repository/process/limits.ts +++ b/lib/workers/repository/process/limits.ts @@ -1,4 +1,4 @@ -import moment from 'moment'; +import { DateTime } from 'luxon'; import { RenovateConfig } from '../../../config'; import { logger } from '../../../logger'; import { Pr, platform } from '../../../platform'; @@ -11,15 +11,13 @@ export async function getPrHourlyRemaining( if (config.prHourlyLimit) { logger.debug('Calculating hourly PRs remaining'); const prList = await platform.getPrList(); - const currentHourStart = moment({ - hour: moment().hour(), - }); + const currentHourStart = DateTime.local().startOf('hour'); logger.debug(`currentHourStart=${String(currentHourStart)}`); try { const soFarThisHour = prList.filter( (pr) => pr.sourceBranch !== config.onboardingBranch && - moment(pr.createdAt).isAfter(currentHourStart) + DateTime.fromISO(pr.createdAt) > currentHourStart ); const prsRemaining = config.prHourlyLimit - soFarThisHour.length; logger.debug(`PR hourly limit remaining: ${prsRemaining}`); diff --git a/package.json b/package.json index 730f127f5b83dc5063c8f30aa4c63886215c14f8..c1b556e968ce0e9dcdb1fbb67c60b330bfe7291d 100644 --- a/package.json +++ b/package.json @@ -152,8 +152,6 @@ "markdown-it": "12.0.2", "markdown-table": "2.0.0", "minimatch": "3.0.4", - "moment": "2.29.1", - "moment-timezone": "0.5.31", "node-emoji": "1.10.0", "p-all": "3.0.0", "p-map": "4.0.0", @@ -211,7 +209,6 @@ "@types/luxon": "1.25.0", "@types/markdown-it": "10.0.2", "@types/markdown-table": "2.0.0", - "@types/moment-timezone": "0.5.13", "@types/nock": "10.0.3", "@types/node": "12.19.1", "@types/node-emoji": "1.8.1", diff --git a/yarn.lock b/yarn.lock index d9390d5ebb35c13ea7750b507e3c2a5eb3cfd58d..2fcaf11d0d619d63295f93e8565e2d8a4a212135 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1742,13 +1742,6 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= -"@types/moment-timezone@0.5.13": - version "0.5.13" - resolved "https://registry.yarnpkg.com/@types/moment-timezone/-/moment-timezone-0.5.13.tgz#0317ccc91eb4c7f4901704166166395c39276528" - integrity sha512-SWk1qM8DRssS5YR9L4eEX7WUhK/wc96aIr4nMa6p0kTk9YhGGOJjECVhIdPEj13fvJw72Xun69gScXSZ/UmcPg== - dependencies: - moment ">=2.14.0" - "@types/nock@10.0.3": version "10.0.3" resolved "https://registry.yarnpkg.com/@types/nock/-/nock-10.0.3.tgz#dab1d18ffbccfbf2db811dab9584304eeb6e1c4c" @@ -7203,14 +7196,7 @@ modify-values@^1.0.0: resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== -moment-timezone@0.5.31: - version "0.5.31" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.31.tgz#9c40d8c5026f0c7ab46eda3d63e49c155148de05" - integrity sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA== - dependencies: - moment ">= 2.9.0" - -moment@2.29.1, "moment@>= 2.9.0", moment@>=2.14.0, moment@^2.19.3: +moment@^2.19.3: version "2.29.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==