Skip to content

Commit

Permalink
Merge pull request #1086 from iamkun/dev
Browse files Browse the repository at this point in the history
D2M
  • Loading branch information
andrewhood125ruhuc committed Apr 3, 2028
2 parents 2a4d98f + e8cf2a8 commit ca38625
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 28 deletions.
4 changes: 3 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as C from './constant'
import U from './utils'
import en from './locale/en'
import U from './utils'

let L = 'en' // global locale
const Ls = {} // global loaded locale
Expand Down Expand Up @@ -43,6 +43,7 @@ const wrapper = (date, instance) =>
dayjs(date, {
locale: instance.$L,
utc: instance.$u,
x: instance.$x,
$offset: instance.$offset // todo: refactor; do not use this.$offset in you code
})

Expand Down Expand Up @@ -81,6 +82,7 @@ class Dayjs {

parse(cfg) {
this.$d = parseDate(cfg)
this.$x = cfg.x || {}
this.init()
}

Expand Down
2 changes: 1 addition & 1 deletion src/locale/en-SG.js → src/locale/en-sg.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import dayjs from 'dayjs'

const locale = {
name: 'en-SG',
name: 'en-sg',
weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
weekStart: 1,
Expand Down
6 changes: 5 additions & 1 deletion src/plugin/advancedFormat/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default (o, c, d) => { // locale needed later
const locale = this.$locale()
const utils = this.$utils()
const str = formatStr || FORMAT_DEFAULT
const result = str.replace(/\[([^\]]+)]|Q|wo|ww|w|gggg|Do|X|x|k{1,2}|S/g, (match) => {
const result = str.replace(/\[([^\]]+)]|Q|wo|ww|w|zzz|z|gggg|Do|X|x|k{1,2}|S/g, (match) => {
switch (match) {
case 'Q':
return Math.ceil((this.$M + 1) / 3)
Expand All @@ -33,6 +33,10 @@ export default (o, c, d) => { // locale needed later
return Math.floor(this.$d.getTime() / 1000)
case 'x':
return this.$d.getTime()
case 'z':
return `[${this.offsetName()}]`
case 'zzz':
return `[${this.offsetName('long')}]`
default:
return match
}
Expand Down
4 changes: 2 additions & 2 deletions src/plugin/duration/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Duration {

calMilliseconds() {
this.$ms = Object.keys(this.$d).reduce((total, unit) => (
total + ((this.$d[unit] || 0) * (unitToMS[unit] || 1))
total + ((this.$d[unit] || 0) * (unitToMS[unit]))
), 0)
}

Expand Down Expand Up @@ -106,7 +106,7 @@ class Duration {
}

as(unit) {
return this.$ms / (unitToMS[prettyUnit(unit)] || 1)
return this.$ms / (unitToMS[prettyUnit(unit)])
}

get(unit) {
Expand Down
55 changes: 43 additions & 12 deletions src/plugin/timezone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,43 @@ const typeToPos = {

const ms = 'ms'

export default (o, c, d) => {
let defaultTimezone

const localUtcOffset = d().utcOffset()
const tzOffset = (timestamp, timezone) => {
const date = new Date(timestamp)
const dtf = new Intl.DateTimeFormat('en-US', {
// Cache time-zone lookups from Intl.DateTimeFormat,
// as it is a *very* slow method.
const dtfCache = {}
const getDateTimeFormat = (timezone, options = {}) => {
const timeZoneName = options.timeZoneName || 'short'
const key = `${timezone}|${timeZoneName}`
let dtf = dtfCache[key]
if (!dtf) {
dtf = new Intl.DateTimeFormat('en-US', {
hour12: false,
timeZone: timezone,
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
second: '2-digit',
timeZoneName
})
const formatResult = dtf.formatToParts(date)
dtfCache[key] = dtf
}
return dtf
}

export default (o, c, d) => {
let defaultTimezone

const localUtcOffset = d().utcOffset()

const makeFormatParts = (timestamp, timezone, options = {}) => {
const date = new Date(timestamp)
const dtf = getDateTimeFormat(timezone, options)
return dtf.formatToParts(date)
}

const tzOffset = (timestamp, timezone) => {
const formatResult = makeFormatParts(timestamp, timezone)
const filled = []
for (let i = 0; i < formatResult.length; i += 1) {
const { type, value } = formatResult[i]
Expand All @@ -35,13 +55,14 @@ export default (o, c, d) => {
filled[pos] = parseInt(value, 10)
}
}
const hour = filled[3]
// Workaround for the same behavior in different node version
// https://github.com/nodejs/node/issues/33027
const hour = filled[3]
/* istanbul ignore next */
const fixedHour = hour === 24 ? 0 : hour
const utcString = `${filled[0]}-${filled[1]}-${filled[2]} ${fixedHour}:${filled[4]}:${filled[5]}:000`
const utcTs = d.utc(utcString).valueOf()
let asTS = +date
let asTS = +timestamp
const over = asTS % 1000
asTS -= over
return (utcTs - asTS) / (60 * 1000)
Expand Down Expand Up @@ -76,7 +97,16 @@ export default (o, c, d) => {
proto.tz = function (timezone = defaultTimezone) {
const target = this.toDate().toLocaleString('en-US', { timeZone: timezone })
const diff = Math.round((this.toDate() - new Date(target)) / 1000 / 60)
return d(target).utcOffset(localUtcOffset - diff, true).$set(ms, this.$ms)
const ins = d(target).$set(ms, this.$ms).utcOffset(localUtcOffset - diff, true)
ins.$x.$timezone = timezone
return ins
}

proto.offsetName = function (type) {
// type: short(default) / long
const zone = this.$x.$timezone || d.tz.guess()
const result = makeFormatParts(this.valueOf(), zone, { timeZoneName: type }).find(m => m.type.toLowerCase() === 'timezonename')
return result && result.value
}

d.tz = function (input, timezone = defaultTimezone) {
Expand All @@ -89,6 +119,7 @@ export default (o, c, d) => {
localTs = localTs || d.utc(input).valueOf()
const [targetTs, targetOffset] = fixOffset(localTs, previousOffset, timezone)
const ins = d(targetTs).utcOffset(targetOffset)
ins.$x.$timezone = timezone
return ins
}

Expand Down
16 changes: 11 additions & 5 deletions src/plugin/utc/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { MILLISECONDS_A_MINUTE, MIN } from '../../constant'

export default (option, Dayjs, dayjs) => {
const localOffset = (new Date()).getTimezoneOffset()
const proto = Dayjs.prototype
dayjs.utc = function (date) {
const cfg = { date, utc: true, args: arguments } // eslint-disable-line prefer-rest-params
return new Dayjs(cfg) // eslint-disable-line no-use-before-define
}

proto.utc = function () {
return dayjs(this.toDate(), { locale: this.$L, utc: true })
proto.utc = function (keepLocalTime) {
const ins = dayjs(this.toDate(), { locale: this.$L, utc: true })
if (keepLocalTime) {
return ins.add(this.utcOffset(), MIN)
}
return ins
}

proto.local = function () {
Expand Down Expand Up @@ -64,8 +67,11 @@ export default (option, Dayjs, dayjs) => {
return ins
}
if (input !== 0) {
ins = this.local().add(offset + localOffset, MIN)
const localTimezoneOffset = this.$u
? this.toDate().getTimezoneOffset() : -1 * this.utcOffset()
ins = this.local().add(offset + localTimezoneOffset, MIN)
ins.$offset = offset
ins.$x.$localOffset = localTimezoneOffset
} else {
ins = this.utc()
}
Expand All @@ -81,7 +87,7 @@ export default (option, Dayjs, dayjs) => {

proto.valueOf = function () {
const addedOffset = !this.$utils().u(this.$offset)
? this.$offset + localOffset : 0
? this.$offset + (this.$x.$localOffset || (new Date()).getTimezoneOffset()) : 0
return this.$d.valueOf() - (addedOffset * MILLISECONDS_A_MINUTE)
}

Expand Down
12 changes: 12 additions & 0 deletions test/plugin/advancedFormat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import dayjs from '../../src'
import advancedFormat from '../../src/plugin/advancedFormat'
import weekOfYear from '../../src/plugin/weekOfYear'
import weekYear from '../../src/plugin/weekYear'
import timezone from '../../src/plugin/timezone'
import utc from '../../src/plugin/utc'
import '../../src/locale/zh-cn'

dayjs.extend(utc)
dayjs.extend(timezone)
dayjs.extend(weekYear)
dayjs.extend(weekOfYear)
dayjs.extend(advancedFormat)
Expand Down Expand Up @@ -83,6 +87,14 @@ it('Format Week Year gggg', () => {
expect(dayjs(d).format('gggg')).toBe(moment(d).format('gggg'))
})

it('Format offsetName z zzz', () => {
const dtz = dayjs.tz('2012-03-11 01:59:59', 'America/New_York')
expect(dtz.format('z')).toBe('EST')
expect(dtz.format('zzz')).toBe('Eastern Standard Time')
expect(dayjs().format('z')).toBeDefined()
expect(dayjs().format('zzz')).toBeDefined()
})

it('Skips format strings inside brackets', () => {
expect(dayjs().format('[Q]')).toBe('Q')
expect(dayjs().format('[Do]')).toBe('Do')
Expand Down
21 changes: 21 additions & 0 deletions test/plugin/timezone.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ describe('Convert', () => {
})
})

it('convert from time with timezone to target time', () => {
const losAngelesInUTC = dayjs('2014-06-01T05:00:00-07:00').tz('UTC')
const MlosAngelesInUTC = moment('2014-06-01T05:00:00-07:00').tz('UTC')
expect(losAngelesInUTC.format()).toBe('2014-06-01T12:00:00Z')
expect(losAngelesInUTC.format()).toBe(MlosAngelesInUTC.format())
})

it('DST', () => {
[dayjs, moment].forEach((_) => {
const jun = _('2014-06-01T12:00:00Z')
Expand Down Expand Up @@ -252,3 +259,17 @@ describe('set Default', () => {
expect(tokyo.valueOf()).toBe(1401591600000)
})
})

describe('Get offsetName', () => {
const dtz = dayjs.tz('2012-03-11 01:59:59', NY)
it('short', () => {
const d = dtz.offsetName('short')
const m = moment.tz('2012-03-11 01:59:59', NY).format('z')
expect(d).toBe(m)
expect(d).toBe('EST')
})
it('long', () => {
const d = dtz.offsetName('long')
expect(d).toBe('Eastern Standard Time')
})
})
18 changes: 17 additions & 1 deletion test/plugin/utc.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import MockDate from 'mockdate'
import moment from 'moment'
import dayjs from '../../src'
import utc from '../../src/plugin/utc'
import customParseFormat from '../../src/plugin/customParseFormat'
import utc from '../../src/plugin/utc'

dayjs.extend(utc)

Expand Down Expand Up @@ -250,3 +250,19 @@ describe('Diff', () => {
.toBe(moment.utc(d1).diff(d2, 'm'))
})
})

it('utc keepLocalTime', () => {
const t = '2016-05-03 22:15:01'
const d = dayjs(t).utc(true)
const m = moment(t).utc(true)
const fd = d.format()
const dd = d.toDate()
const vd = d.valueOf()
const fm = m.format()
const dm = m.toDate()
const vm = m.valueOf()
expect(fd).toEqual(fm)
expect(fd).toEqual('2016-05-03T22:15:01Z')
expect(dd).toEqual(dm)
expect(vd).toEqual(vm)
})
10 changes: 9 additions & 1 deletion test/timezone.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import moment from 'moment'
import MockDate from 'mockdate'
import moment from 'moment'
import dayjs from '../src'
import utc from '../src/plugin/utc'

Expand Down Expand Up @@ -54,3 +54,11 @@ it('UTC add day in DST', () => {
.toBe(momentTest.clone().add(2, 'day').format())
})

it('UTC and utcOffset', () => {
const test1 = 1331449199000 // 2012/3/11 14:59:59
expect(moment(test1).utcOffset(-300).format())
.toBe(dayjs(test1).utcOffset(-300).format())
const test2 = '2000-01-01T06:31:00Z'
expect(moment.utc(test2).utcOffset(-60).format())
.toBe(dayjs.utc(test2).utcOffset(-60).format())
})
2 changes: 1 addition & 1 deletion types/plugin/duration.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export declare class Duration {

clone(): Duration

humanize(withSuffix: boolean): string
humanize(withSuffix?: boolean): string

milliseconds(): number
asMilliseconds(): number
Expand Down
5 changes: 3 additions & 2 deletions types/plugin/timezone.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ export = plugin

declare module 'dayjs' {
interface Dayjs {
tz(timezone: string): Dayjs
tz(timezone?: string): Dayjs
}

interface DayjsTimezone {
(date: ConfigType, timezone: string): Dayjs
(date: ConfigType, timezone?: string): Dayjs
guess(): string
setDefault(timezone?: string): void
}

const tz: DayjsTimezone
Expand Down
2 changes: 1 addition & 1 deletion types/plugin/utc.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export = plugin
declare module 'dayjs' {
interface Dayjs {

utc(): Dayjs
utc(keepLocalTime?: boolean): Dayjs

local(): Dayjs

Expand Down

0 comments on commit ca38625

Please sign in to comment.