前端对时间utc的处理

本文最后更新于:2023-05-18 09:33:19

背景

​ 海外业务在时间上可能会显示当地时间,而后端一般存在库里的是零时区的时间,在前端展示时需要对0时区时间进行处理,展示正确的时间

使用

Demo1: 后端返回的是时间戳 1658825542000

Demo2: 后端返回的是时间字符串 2022-07-26 08:52:22

demo1和demo2都是0时区的时间(即utc时间)

  1. 转换为固定时区的时间,如尼日利亚 (1时区),北京(8时区)
  2. 转换为页面时区的时间,如尼日利亚 (1时区),北京(8时区)

dayjs

注意:dayjs需要引入utc插件

如果后端返回的不是常规的时间格式,需要引入customParseFormat去解析时间后再做处理

  • dayjs-utc

    1
    2
    dayjs().format() //2019-03-06T08:00:00+08:00
    dayjs().utc().format() // 2019-03-06T00:00:00Z
  • dayjs-offset

    • 获取 UTC 偏移量 (分钟)

    • 如果输入在-16到16之间,会将您的输入理解为小时数而非分钟。

1
2
3
4
5
6
7
8
9
// 引入依赖
import dayjs from "dayjs";
const utc = require("dayjs/plugin/utc");
const customParseFormat = require("dayjs/plugin/customParseFormat");
dayjs.extend(customParseFormat);
dayjs.extend(utc);

const timeStamp = 1658825542000
const timeStr = '2022-07-26 08:52:22'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 时区枚举
const Timezone = {
Nigeria: 1,
China: 8
};

// 如果时间格式是时间戳,需要使用dayjs.utc(timeStamp)去处理时间戳
// 否则会被解析为当前时间
export function zeroToFixedTimezone1(timeStamp, timezone, format = "MMM DD,YYYY HH:mm:ss") {
return dayjs.utc(timeStamp) // 注意!!!
.add(timezone, "hour")
.format(format);
}

// 如果时间格式是时间字符,使用dayjs.utc(timeStr)和dayjs(timeStr)是一样的结果
export function zeroToFixedTimezone2(timeStr, timezone, format = "MMM DD,YYYY HH:mm:ss") {
return dayjs(timeStr) // 或者dayjs.utc(timeStr)
.add(timezone, "hour")
.format(format);
}

export function utcOffsetDate(date, format = "MMM DD,YYYY HH:mm:ss") {
const utcOffset = dayjs().utcOffset();
return dayjs.utc(date).add(utcOffset, "m")
.format(format);
}

zeroToFixedTimezone1(1658825542000, Timezone.Nigeria) // Jul 26,2022 09:52:22
zeroToFixedTimezone2(1658825542000, Timezone.Nigeria) // Jul 26,2022 17:52:22 //!!!错误用法 北京时间 相当于比0时区大了9个小时,比尼日大了8个小时
zeroToFixedTimezone2('2022-08-26 08:52:22', Timezone.Nigeria) // Jul 26,2022 09:52:22

utcOffsetDate(1658825542000) // Jul 26,2022 16:52:22 北京时间 相当于比0时区大了8个小时
utcOffsetDate('2022-08-26 08:52:22') // Jul 26,2022 16:52:22 北京时间 相当于比0时区大了8个小时

moment

  • moment-utc

  • moment-offset

    ​ 此函数返回 UTC 的实际偏移量,而不是反向偏移量(类似 Date.prototype.getTimezoneOffset 返回的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import moment from 'moment'
// 类似dayjs,但是不需要安装插件

// 时区枚举
const Timezone = {
Nigeria: 1,
China: 8
};

// 如果时间格式是时间戳,需要使用dayjs.utc(timeStamp)去处理时间戳
// 否则会被解析为当前时间
export function zeroToFixedTimezone1(timeStamp, timezone, format = "MMM DD,YYYY HH:mm:ss") {
return moment.utc(timeStamp) // 注意!!!
.add(timezone, "hour")
.format(format);
}

// 如果时间格式是时间字符,使用dayjs.utc(timeStr)和dayjs(timeStr)是一样的结果
export function zeroToFixedTimezone2(timeStr, timezone, format = "MMM DD,YYYY HH:mm:ss") {
return moment(timeStr) // 或者dayjs.utc(timeStr)
.add(timezone, "hour")
.format(format);
}

export function utcOffsetDate(date, format = "MMM DD,YYYY HH:mm:ss") {
const utcOffset = moment().utcOffset();
return moment.utc(date).add(utcOffset, "m")
.format(format);
}

zeroToFixedTimezone1(1658825542000, Timezone.Nigeria) // Jul 26,2022 09:52:22
zeroToFixedTimezone2(1658825542000, Timezone.Nigeria) // Jul 26,2022 17:52:22 //!!!错误用法 北京时间 相当于比0时区大了9个小时,比尼日大了8个小时
zeroToFixedTimezone2('2022-08-26 08:52:22', Timezone.Nigeria) // Jul 26,2022 09:52:22

utcOffsetDate(1658825542000) // Jul 26,2022 16:52:22 北京时间 相当于比0时区大了8个小时
utcOffsetDate('2022-08-26 08:52:22') // Jul 26,2022 16:52:22 北京时间 相当于比0时区大了8个小时

原生js

反向偏移量Date.prototype.getTimezoneOffset跟 dayjs和moment是相反的

Date.getTimezoneOffset是分钟为单位的

时间戳: 如果时间格式是时间戳,需要使用dayjs.utc(timeStamp)去处理时间戳

时间字符串: 如果时间格式是时间字符,使用dayjs.utc(timeStr)和dayjs(timeStr)是一样的结果

最好的方案:都使用dayjs.utc(date)去解析时间