js设置北京时区_盘一盘 Python 系列特别篇十九之 时区和夏时令

本文介绍了时区的概念,以北京和美国东部时区为例,探讨了UTC作为时间基准的重要性。通过Python的datetime模块展示了如何设置和转换时区,并解释了夏令时对时间差异的影响。文章还提到了JavaScript中设置北京时区的方法,并强调了在处理跨时区时间时,转换为UTC进行比较的必要性。
摘要由CSDN通过智能技术生成
本文含  6625  字, 12  图表截屏 建议阅读  34  分钟1时区时间差

在每个地区,中午 12 点都对应着正午,但是每个地区的 12 点是统一时刻吗?显然不是,要不然也不会有时差概念了。下图最右边的图显示着火车穿过两个时区,那么记录的时间应该是处在时区的那个时间,因此区分时区很重要。

083809555822cc9878af5ccc5ab38f9f.png

世界上不同地区显示的时间不同,北京时间就比美国东部时间快 13 个小时,看下图:

9205225255b4e636a9b64bed26afc223.png

UTC

为了方便比较不同时区的时间,我们用协调世界时间当作基准。

协调世界时间 (Coordinated Universal Time, UTC) 是最主要的世界时间标准,在在时刻上尽量接近于格林威治标准时间 (Greenwich Mean Time, GMT)。UTC 可以视为一个世界统一的时间,其他时区的时间都是在这个基础上增加或减少的,比如

  • 北京和新加坡的时间比 UTC 快 8 小時,可记做 UTC + 8

  • 美国东部时区时间比 UTC 慢 5 个小时,可记做 UTC - 5

这样看北京时间比美东时间快 13 个小时,因为 UTC + 8 - (UTC - 5) = 13。有了标准 UTC,时间就可以比较了。

0509dab45e9f53ddac716e8dca6060ce.png

当用 datetime() 对象创建时间式,如果不设定时区,那么这个时间被称为不考虑时区 (UTC-naive) 的日期时间;如果设定时区,那么这个时间被称为考虑时区 (UTC-aware) 的日期时间。

from datetime import datetime, timedelta, timezone

创建一个不考虑时区的日期时间,如果你处理的问题不需要考虑多个时区,那么这个时间可看做是你处理问题所在地区的时间;如果你处理的问题需要考虑多个时区,那么这个时间可看做是 UTC。

dt = datetime(2020, 6, 27, 21, 30)print(dt)
2020-06-27 21:30:00

已知美国东部时区时间比 UTC 慢 5 个小时,因此可用 timedelta() 对象定义一个负 5 个小时的时间差,并传入 timezone() 对象中定义美东时区 ET

ET = timezone(timedelta(hours=-5))dt = datetime(2020, 6, 27, 21, 30, tzinfo=ET)print(dt)
2020-06-27 21:30:00-05:00

打印出来的日期时间都是当地时间 (此时是美东时间),而最后有 -05:00 的字样,它叫做 UTC offset,负号代表比 UTC 慢 5 个小时。

已知北京时间比 UTC 快 8 个小时,因此可用 timedelta() 对象定义一个正 8 个小时的时间差,并传入 timezone() 对象中定义北京时区 BJ

BJ = timezone(timedelta(hours=8))dt = datetime(2020, 6, 27, 21, 30, tzinfo=BJ)print(dt)
2020-06-27 21:30:00+08:00
astimezone()

打印出来的都是当地时间 (此时是北京时间),而最后有 +08:00 的字样,它叫做 UTC offset,正号代表比 UTC 快 8 个小时。

现在定义一个美东时间 dt 为 2020-06-27 早上 9 点 30 分,用 astimezone() 对象显示出对应的北京时间是多少,结果是 2020-06-27 晚上 22 点 30 分。但两者的绝对差异是零。这个现实被称作相同时刻,不同时间 (same moment, different time)

dt = datetime(2020, 6, 27, 9, 30, tzinfo=ET)print(f'美东时间:{dt}')print(f'北京时间:{dt.astimezone(BJ)}')print(dt.astimezone(BJ)-dt)
美东时间:2020-06-27 09:30:00-05:00
北京时间:2020-06-27 22:30:00+08:00
0:00:00

同理,定义一个北京时间 dt 为 2020-06-27 晚上 22 点 30 分,用 astimezone() 对象显示出对应的美东时间是多少,结果是 2020-06-27 早上 9 点 30 分。两者的绝对差异是零。相同时刻,不同时间

dt = datetime(2020, 6, 27, 22, 30, tzinfo=BJ)print(f'北京时间:{dt}')print(f'美东时间:{dt.astimezone(ET)}')print(dt.astimezone(ET)-dt)
北京时间:2020-06-27 22:30:00+08:00
美东时间:2020-06-27 09:30:00-05:00
0:00:00
replace()

dt.replace(some_tz) 函数返回一个具有同样值的日期,但是在不同时区,即 dt 的时区和 some_tz 时区不同,这个叫做相同时间,不同时刻 (same time, different moment)

dt = datetime(2020, 6, 27, 9, 30, tzinfo=ET)dt_to_utc = dt.replace(tzinfo=timezone.utc)dt_as_utc = dt.astimezone(timezone.utc)print(dt)print(dt_to_utc)print(dt_as_utc)print(dt - dt_to_utc)print(dt - dt_as_utc)
2020-06-27 09:30:00-04:00
2020-06-27 09:30:00+00:00
2020-06-27 13:30:00+00:00
4:00:00
0:00:00

从上面结果可看出两点:

  • dt_to_utc 和 dt 是相同时间 (都是 2020-06-27 09:30:00),不同时刻 (从它俩的 UTC offset 或者它俩之差 4:00:00 看出来)

  • dt_as_utc 和 dt 是不同时间 (前者是 14:30:00 后者是 09:30:00),相同时刻 (从它俩之差是 0:00:00 看出来)

dateutil.tz

在实际操作做很难记住每个时区的时间和 UTC 差多少,幸运的是 dateutil 包里的 tz 对象可以帮我们解决这个难题。只需用 '区域/城市' 来设定时区就可以了,比如

  • 美东时间用 'America/New_York' 来设定

  • 北京时间用 'China/Bei_Jing' 来设定

tz 是 timezone 的缩写,可看成是时区的数据库,首先从 dateutil 引入它,然后用 gettz() 函数加上设定的字符串时区来获取时区对象。

from dateutil import tzET = tz.gettz('America/New_York')BJ = tz.gettz('China/Bei_Jing')

以下结果复制了上面结果,只不过现在用 tz.gettz() 加字符串来设置时区,而上面用 timezone(timedelta()) 加时间差来设置时区。对普通人来说,记住形象的字符串比记住枯燥的时差容易多了吧。

dt = datetime(2020, 6, 27, 9, 30, tzinfo=ET)dt_to_bj = dt.replace(tzinfo=BJ)dt_as_bj = dt.astimezone(BJ)print(dt)print(dt_to_bj)print(dt_as_bj)print(dt - dt_to_bj)print(dt - dt_as_bj)
2020-06-27 09:30:00-04:00
2020-06-27 09:30:00+08:00
2020-06-27 21:30:00+08:00
12:00:00
0:00:00

提示:注意力放在 dt - dt_to_bj 的结果 12:00:00 上,美东时间比北京时间慢了 12 个小时。

现在突发奇想换个日期 2020-01-11 看看有什么变化?

dt = datetime(2020, 1, 11, 9, 30, tzinfo=ET)dt_to_bj = dt.replace(tzinfo=BJ)dt_as_bj = dt.astimezone(BJ)print(dt)print(dt_to_bj)print(dt_as_bj)print(dt - dt_to_bj)print(dt - dt_as_bj)
2020-01-11 09:30:00-05:00
2020-01-11 09:30:00+08:00
2020-01-11 22:30:00+08:00
13:00:00
0:00:00

这时 dt - dt_to_bj 的结果是 13:00:00 上,表示美东时间比北京时间慢了 13 个小时 (之前只慢了 12 个小时)。此外更明显的是,

  • 当日期为 2020-06-27,北京时间是 2020-06-27 21:30:00+08:00

  • 当日期为 2020-01-11,北京时间是 2020-01-11 22:30:00+08:00

为什么不同日期上同样的美东时间对应的北京时间会不同呢?时间差还能随日期变?你说对了,夏令时了解一下。

2夏令时

夏令时 (daylight saving time, DST) 则是为了充分利用夏天日照长的特点,充分利用光照节约能源而人为调整时间的一种机制。通过在夏天将时间向前加一小时,使人们早睡早起节约能源。虽然很多西方国家都采用了DST,但是中国不采用 DST。

夏令时 (daylight saving time) 是由“创始人”本杰明·富兰克林提出,他在 1784 年发表《节约日光成本的经济工程》, 原因是注意到人们 10 点后才起床,夜生活过到深夜。所以建议大家早睡早起,每年可节省不少蜡烛。但他没能目睹这天到来。在第一次世界大战期间,美国首次实施日光节约,以此来节省燃料。1966年,约翰逊总统签署了统一时间法案,才使其成为法律。

美股开盘时间在中国的晚上,因为美国有夏令时间 , 因此夏天的交易时间与冬天相比会提前一小时:

  • 在冬天交易时间为美国东部时间 9:30 到 16:00,对应着北京时间 22:30 到次日 5:00

  • 在夏天交易时间为美国东部时间 9:30 到 16:00,对应着北京时间 21:30 到次日 4:00

4ac17bf9d53f49611ad02d3cc8e66e71.png

在 2020 年,夏令时是从 3 月 8 日早上 2 点开始,到 11 月 1 日早上 2 点结束。

夏令时的起点 (将表前拨)

在 3 月 8 日早上 2 点,大家把表往前调 1 个小时到早上 3 点,感觉是 2 点到 3 点这一段的时间突然没有了,如下图所示:

20086ab311d1a2dcd98c3fd5db110b03.png

但是对应到 UTC 上,这段时间根本没有消失,只不过美东时间的 UTC offset 变了,由原来的 UTC-5 变成了 UTC-4,即从原来正常的慢 5 个小时到现在慢 4 个小时,如下图所示:

6226e3d8fde2dc9c1a15768c55e47ee3.png

ET = tz.gettz('US/Eastern')spring_159am = datetime(2020, 3, 8, 1, 59, 59, tzinfo=ET)spring_3am = datetime(2020, 3, 8, 3, 0, 0, tzinfo=ET)print(spring_159am)print(spring_3am)(spring_3am - spring_159am).total_seconds()
2020-03-08 01:59:59-05:00
2020-03-08 03:00:00-04:00
3601.0
spring_159am = spring_159am.astimezone(tz.UTC)spring_3am = spring_3am.astimezone(tz.UTC)print(spring_159am)print(spring_3am)(spring_3am - spring_159am).total_seconds()
2020-03-08 06:59:59+00:00
2020-03-08 07:00:00+00:00
1.0
夏令时的终点 (将表后拨)

在 11 月 1 日早上 2 点,大家把表往后调 1 个小时到早上 1 点,把之前“丢失的那一个小时找回来了”,回归正常。注意在调时间这个动作点 (夏令时终点) 的前后从“1 点到 2 点”的时间段有歧义,它们既可以指夏令时结束之前的时间段,也可以指夏令时结束之后的时间段。为了偏于说明,用两个时间轴来区分,如下图所示:

5b0fc64c6fa3593b1adb9f760908f247.png

但是对应到 UTC 上,丢失的那一个小时找回来,使得对应的美东时间的 UTC offset 变了,由原来的 UTC-4 变成了 UTC-5,即从原来慢 4 个小时又回到正常情况的慢 5 个小时,如下图所示:

16996d4d210579f504b226f4b1fdc1a1.png

ET = tz.gettz('US/Eastern')

首先用 datetime_ambiugous() 函数来验证在早上 1 点到 2 点这段时间段中的时间是否有歧义:

  • 1:00:00 有歧义

  • 1:59:59 有歧义

  • 2:00:00 无歧义

first_1am = datetime(2020, 11, 1, 1, 0, 0, tzinfo=ET)tz.datetime_ambiguous(first_1am)first_159am = datetime(2020, 11, 1, 1, 59, 59, tzinfo=ET)tz.datetime_ambiguous(first_159am)first_2am = datetime(2020, 11, 1, 2, 2, 0, tzinfo=ET)tz.datetime_ambiguous(first_2am)
True
True
False

由于 1:00:00 这个时点有歧义,我们先创建两个日期时间对象 first_1am 和 second_1am,发现两者在 ET 时区和 UTC 的时间差都为零。

first_1am = datetime(2020, 11, 1, 1, 0, 0, tzinfo=ET)second_1am = datetime(2020, 11, 1, 1, 0, 0, tzinfo=ET)(second_1am - first_1am).total_seconds()
0.0
first_1am = first_1am.astimezone(tz.UTC)second_1am = second_1am.astimezone(tz.UTC)(second_1am - first_1am).total_seconds()
0.0

那这样就无法实现夏令时结束“时间回调”这个现象了,好在我们用 enfold() 函数,它将有歧义的时间“折叠”起来,使得转换成 UTC 时能考虑到“时间回调”。从 first_1am 和 second_1am 之间的时间差为 3600 秒可以看出 enfold() 函数的作用了。

first_1am = datetime(2020, 11, 1, 1, 0, 0, tzinfo=ET)second_1am = datetime(2020, 11, 1, 1, 0, 0, tzinfo=ET)second_1am = tz.enfold(second_1am)(second_1am - first_1am).total_seconds()
0.0
first_1am = first_1am.astimezone(tz.UTC)second_1am = second_1am.astimezone(tz.UTC)(second_1am - first_1am).total_seconds()
3600.0

将两者表示成美东时间,发现 first_1am 是夏令时结束前的早上 1 点钟,比 UTC 慢 4 小时,而 second_1am 是夏令时结束后的早上 1 点钟,比 UTC 慢 5 小时。

print(first_1am.astimezone(ET))print(second_1am.astimezone(ET))
2020-11-01 01:00:00-04:00
2020-11-01 01:00:00-05:00
3总结

这么清楚的帖子还需要总结吗?需要:

  1. astimezone() 不同时间,相同时刻。

  2. replace() 相同时间,不同时刻。

  3. 用 dateutil.tz 可以方便设定时区

  4. 很多国家有夏令时,一年调节两次时间,先调慢再调快

  5. UTC 是标准,不管你怎么变,对应在 UTC 上的时间不会变,比较不同时区的时间最好转成 UTC 再比较

下帖来讲日期计数惯例 (daycount convention)。

你可能会喜欢

  • Jmeter关联系列_数据驱动中的业务逻辑关联

  • docker搭建接口自动化持续集成框架

  • Python26:使用Folium库生成精美的标记地图

  • 盘一盘 Python 系列基础篇十一之 机器学习 Sklearn

  • 盘一盘 Python 系列特别篇十八之 日期时间 DateTime

  • Linux环境部署之ubuntu网络配置

  • 性能测试指标7:性能测试的阶段性工作

  • jmeter之对jar包进行调用

  • jmeter之爬取网络图片

  • 软件质量保障体系图

  • 研发过程中的测试工作

  • APP测试流程及测试点

  • WEB测试范围小结

作为一个对测试有情怀的人,希望本公众号的文章能够帮助到大家,测试这条路不容易,请大家多多帮忙推广,将越来越多志同道合的小伙伴聚集,在这条道路上互相扶持,一起走下去……

84331023e72bbe3d83142628902b0b02.png

测试交流,加我备注【测试交流】拉入交流群,更有不定期资料赠送,敬请期待

41268258c33e6380062aa193a5571028.png

福利来一波~~~

关注公众号回复以下信息送免费资料
回复Jenkins 领取Jenkins学习资料回复Jmeter 领取Jmeter学习资料

回复Java   领取Java学习资料

回复Python 领取python入门资料

回复RobotFramework   领取RobotFramework 框架搭建资料

本文转载自【公众号:王的机器

c2d021911c7842c1474e5e7e3d895bd5.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值