标准时和夏令时

957 阅读3分钟

夏令时

即 Daylight Saving Time,每年

3月第2个星期日凌晨02:00

开始,到

11月第1个星期日凌晨02:00

为止。

由来

夏令时开始后,时钟会拨快一个小时,据说其本意是让人们早睡早起,以达到节约能源的目的 -- 早点睡就不用开灯了嘛。夏令时的另一个功用,是让人们在下班后,有足够的时间与孩子们在户外玩耍。春夏回暖,是户外活动的好季节。调成夏令时后,即使是晚上8点,外头仍旧有足够的亮度,让孩子们安全玩耍。

夏令时在11月才结束的原因也是为了儿童安全。10月31日是万圣节,小孩子晚上会出去讨糖果,因为是夏令时,晚上7、8点小孩子出去的时候,天色还够亮,家长也放心些。

带来的问题

  • 每年一次的“空白1小时”(2020-03-08)

  • 两点整 过了1秒之后是 三点零一分

  • 当前时刻:02:00:00 PST

  • 当前时刻:03:00:00 PDT

  • 当前时刻的下一秒:03:00:01 PDT

  • 每年一次的“重复1小时”(2020-11-01)

  • 一点到两点过完之后会再次经过一边

  • 01:00:00 DST -- 02:00:00 DST

  • 01:00:00 PST -- 02:00:00 PST

我们的问题

  • 描述:运营在配置排期的时候会选择:年、月、日、时、分、秒(含义: 美国当地时间xxxx-xx-xx xx:xx:xx)

  • 前提:

  • 在需要我们自己处理排期逻辑的情况下(氛围直出)

  • 运营配置可视化,不要配置时间戳之类的

  • 我们不希望运营感知到夏令时的存在(历史处理方式: 选择 -800 或者 -700)

  • 如何解决

  1. 首先假设配置的时刻是标准时,拿到时间戳

  2. 通过某些方法判断时间戳代表的这一刻是否是夏令时

  3. 非夏令时:假设正确,不做任何处理

  4. 夏令时:假设不正确,还原1小时时差的时间戳

  5. 得到正确的时间戳

Node服务端获取某年夏令时的起止时间

var moment = require('moment-timezone');

// 夏令时开始时间(包含此时间点)【标准时 --> 夏令时】
function getDSTStartTimestamp(year) {
    const str = `${year}-03-01 02:00:00 -800`;
    const d = new Date(str);
    const m = moment(d).tz("America/Los_Angeles");
    let weekday = m.weekday();
    if (weekday === 0) {
        weekday = 7;
    }
    const offsetDay = 7 * 2 - weekday;
    const timestamp = d.getTime() + offsetDay * 24 * 60 * 60 * 1000;
    return timestamp;
}

// 夏令时结束时间(不包含此时间点)【夏令时 --> 标准时】
function getDSTEndTimestamp(year) {
    const str = `${year}-11-01 02:00:00 -700`;
    const d = new Date(str);
    const m = moment(d).tz("America/Los_Angeles");
    let weekday = m.weekday();
    if (weekday === 0) {
        weekday = 7;
    }
    const offsetDay = 7 - weekday;
    const timestamp = d.getTime() + offsetDay * 24 * 60 * 60 * 1000;
    return timestamp;
}

const s = getDSTStartTimestamp('2020');
const e = getDSTEndTimestamp('2020');

const startDate = moment(new Date(s)).tz("America/Los_Angeles");
const endDate = moment(new Date(e)).tz("America/Los_Angeles");

console.log('startDate', s, startDate, startDate.isDST());
// 夏令时开始时间:startDate 1583661600000 Moment<2020-03-08T03:00:00-07:00> true

console.log('endDate', e, endDate, endDate.isDST());
// 夏令时结束时间:endDate 1604221200000 Moment<2020-11-01T01:00:00-08:00> false

参考

《美国时间时区及夏令时简介》gonglue.us/8593

《UTC和GMT》:www.cnblogs.com/champyin/p/…