博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ntp时间同步会同步时区吗_如何处理时区并使软件与国际客户同步
阅读量:2526 次
发布时间:2019-05-11

本文共 14568 字,大约阅读时间需要 48 分钟。

ntp时间同步会同步时区吗

When you develop some software you may not think about timezones at first. Unless you live in a country which has to deal with multiple time zones, such as the United States or Russia.

当您开发某些软件时,您可能首先不会考虑时区。 除非您居住在必须处理多个时区的国家/地区,例如美国或俄罗斯。

I recently came across an issue involving timezones. There were some unit tests making assertions about dates that used to work at my office in France but weren't working in Morocco for new members on our team.

我最近遇到了一个涉及时区的问题。 有一些单元测试对以前在法国的办公室工作但对摩洛哥的新成员不起作用的日期作出断言。

‌This was an opportunity for me to learn how to correctly handle dates and times for international software. In this article, I’ll introduce time zone issues and share some rules to follow.

‌这对我来说是一个学习如何正确处理国际软件日期和时间的机会。 在本文中,我将介绍时区问题并分享一些要遵循的规则。

快速介绍时区 (Quick introduction to time zones)

As the earth is kind of a sphere, the sun is rising in Japan while it's setting in America. If everyone used global time, let’s say 09:00 would be sunrise in Japan, but for Americans it would be sunset. Not very handy.

由于地球是一个球体,因此日本落日于美国时太阳正在升起。 如果每个人都使用全球时间,那么假设09:00在日本是日出,但对美国人来说则是日落。 不太方便。

To make sure the time is coordinated with the sun for everyone, it’s necessary to shift from global time according to your location. As a result, the globe gets split into time zones and each gets an offset. This offset is a number of minutes to add to the global time to get your time zone time. It can be either positive or negative.

为了确保所有人的时间都与太阳协调,有必要根据您所在的位置从全球时间转变。 结果,地球仪分为多个时区 ,每个时区都有一个偏移量 。 此偏移量是要添加到全局时间以获取您的时区时间的分钟数。 它可以是正数或负数。

Global time is called , it stands for Coordinated Universal Time. You may also heard about which is a time zone without any offset.

全球时间称为 它表示世界协调时间。 您可能还听说过 ,这是一个没有任何偏移的时区。

For instance, when it’s 10:50 at UTC, it’s also  03:50 in San Francisco with a -0700 offset and 18:50 in Beijing with a +0800 offset. Yet, the shift isn’t only in whole hours: Nepal's offset is +0545. You can check it out on .

例如,在世界标准时间10:50时,在旧金山也是03:50 ,偏移为-0700 ,在北京为18:50 ,偏移+0800 。 但是,这种变化不仅发生在整个小时内:尼泊尔的偏移量是+0545 。 您可以在上查看。

In addition of this offset, which comes with the time zone, some countries also shift clocks twice a year. adds one hour to the time zone offset before summer. Then, the clock is reset to the time zone time in winter. The goal is to make the daytime longer.

除了时区带来的这种偏移外,某些国家/地区还每年两次偏移时钟。 会使之前的时区偏移量增加一小时。 然后,将时钟重置为冬季的时区时间。 目标是延长白天。

The most common way to figure out a time zone is by using the . You end up with a string such as Europe/Paris following the Area/City pattern. Besides, Microsoft maintains its own used on its operating systems. But this can when running cross-platform .NET Core apps.

找出时区的最常见方法是使用 。 您最终会在区域/城市模式之后输入一个字符串,例如Europe/Paris 。 此外,Microsoft维护其操作系统上使用的自己的 。 但是,这可能在运行跨平台的.NET Core应用程序时 。

IANA is still the go-to. The Microsoft database isn't updated often, it contains less history, fairly curious time zone names (eg: Romantic Standard Time) and is error prone. For example, try to not mix up Arab , Arabic and Arabian Standard Time. For more details on each database and their differences, .

IANA仍然是首选。 Microsoft数据库不经常更新,它包含较少的历史记录,相当奇怪的时区名称(例如: Romantic Standard Time ),并且容易出错。 例如,尽量不要混淆ArabArabicArabian Standard Time 。 有关每个数据库及其区别的更多详细信息, 参阅 。

One last thing: there are plenty of ways to write a date. Fortunately, the sets a common rule for date formatting.

最后一件事:有很多写日期的方法。 幸运的是, 为日期格式设置了一条通用规则。

November 11, 2018 at 12:51:43 AM (in a time zone at UTC+00:00)2018-11-05T12:51:43Z <- Z stands for UTCNovember 11, 2018 at 12:51:43 AM (in a time zone at UTC +07:30)2018-11-05T12:51:43+0730

计算机如何处理日期 (How computers handle dates)

Computers are only able to perform operations using numbers. This means that 2020-08-01 +1  is not equal to 2020-08-02 and can’t be handled.

计算机只能使用数字执行操作。 这意味着2020-08-01 +1不等于2020-08-02并且无法处理。

In order to work with dates more easily, we can represent dates as numbers. This is what timestamps are all about. It’s the number of milliseconds elapsed from a pre-defined date (or epoch) to the specified date.

为了更轻松地处理日期,我们可以将日期表示为数字。 这就是时间戳的全部含义。 这是从预定义的日期(或epoch )到指定的日期经过的毫秒数。

Great, let’s choose an epoch then! Actually, the common epoch has already been set and its value is January 1, 1970 (midnight UTC).

太好了,让我们选择一个时代吧! 实际上,已经设定了公共纪元,其值为1970年1月1日(UTC午夜)

To make sure you understood, run the previous snippet in your browser. What? You didn’t get the same result?

为确保您理解,请在浏览器中运行上一个代码段。 什么? 您没有得到相同的结果?

Ok, I cheated a bit to get this result… I should get Thu Jan 01 1970 01:00 GMT+0100 because my computer time zone is set to Europe/Paris.

好的,我作弊了一点以获得这个结果…我应该得到Thu Jan 01 1970 01:00 GMT+0100因为我的计算机时区设置为欧洲/巴黎。

Actually, this moment with a zero timestamp is midnight in Greenwich, but also 05:45 in Mumbai and even 1969-12-31T16:30 in San Francisco when you consider their time zone’s offset.

实际上,时间戳为零的这一时刻在格林威治时间是午夜,在孟买也是05:45 ,在旧金山甚至是1969-12-31T16:30 (考虑到它们的时区偏移)。

Rule #1 : Timestamps are only for saving, not for displaying. It's considered on UTC because it doesn’t include any offset or time zone.
规则#1:时间戳仅用于保存,而不用于显示。 由于它不包含任何偏移量或时区,因此考虑在UTC上使用。

You didn’t get the “right” date before because JavaScript uses your local time zone to show the most accurate date/time to you.

您之前没有得到“正确的”日期,因为JavaScript使用您的本地时区向您显示最准确的日期/时间。

Now, try the following snippet. I’m sure you’ll get the same result as I did:

现在,尝试以下代码片段。 我相信您将获得与我相同的结果:

Yes, the zero timestamp is 1970-01-01T00:00:00 at UTC for everyone around the globe. Still, it’s not true if you choose another time zone.

是的,全球每个人在UTC的零时间戳都是1970-01-01T00:00:00 。 不过,如果您选择其他时区,则并非如此。

To sum up, toString shows the date using your local time zone while toUTCString is based on UTC. Also don’t be fooled by toISOString which is the same as toUTCString but outputs the ISO 8601 format (its name should be toUTCISOString).

综上所述,当toUTCString基于UTC时, toString使用您的本地时区显示日期。 也不要被toISOString欺骗,后者与toUTCString相同,但是输出ISO 8601格式(其名称应为toUTCISOString )。

I recommend the to convert a second timestamp (not milliseconds) into a readable string. Using this command with the UTC option makes sure it doesn't take your computer/browser's time zone into account.

我建议使用将第二个时间戳(不是毫秒)转换为可读的字符串。 将此命令与UTC选项一起使用可确保不考虑计算机/浏览器的时区。

# Linux$ date -d @1586159897 -u Mon Apr  6 07:58:17 UTC 2020# For Osx users$ date -r 1586159897 -u

让我们修复单元测试 (Let’s fix our unit test)

The problem I encountered with time zones was in my unit tests. Take the time to read it and understand what it’s supposed to assert:

我在时区遇到的问题是在单元测试中。 花点时间阅读它,了解它应该声明的内容:

In this test, the goal is to check that setHours sets the date’s hours and minutes to zero (midnight). I first choose a random timestamp which isn’t at midnight. Then compare the result with the timestamp for the same day at midnight.

在此测试中,目标是检查setHours将日期的小时和分钟数设置为零(午夜)。 我首先选择一个不在午夜的随机时间戳。 然后将结果与午夜同一天的时间戳进行比较。

Actually it’s working – but only if your time zone offset is +0200 (including DST) at this moment. For instance, it’s not working for Africa/Casablanca ( +0100 including DST). Let’s see how those timestamps are printed:

实际上,它是有效的-但+0200+0200时区偏移量为+0200 (包括DST)。 例如,它不适用于非洲/卡萨布兰卡( +0100包括DST)。 让我们看看如何打印这些时间戳:

That’s it, the UTC date for both results isn't the same. It also means the resulting timestamps aren’t the same either.

就是这样,两个结果的UTC日期都不同。 这也意味着生成的时间戳也不相同。

As you can see, the offset for Paris is +0200 and +0100 for Casablanca. But both display midnight with toString. This means that the setHours function uses your computer time zone to perform the operation. And toString displays the date using your time zone.

如您所见,巴黎的偏移量是+0200 ,卡萨布兰卡的偏移量是+0100 。 但是两个都显示与toString午夜。 这意味着setHours函数使用您的计算机时区执行操作。 并且toString使用您的时区显示日期。

This is not the only issue with this test: what if you run this test in San Fransisco? Right, the day would be 2020-07-31 for both dates because of the -0700 offset.

这不是此测试的唯一问题:如果您在San Fransisco中运行此测试该怎么办? 是的,由于-0700偏移量,所以两个日期的日期都将是2020-07-31

The safest way to make this test reliable and work all around the world is to use a date in your local time zone. You’ll not use timestamps to set initial dates anymore.

使该测试可靠并且在全球范围内均可使用的最安全方法是在您所在的时区使用日期。 您将不再使用时间戳来设置初始日期。

We can enhance the previous rule about timestamps:

我们可以增强先前有关时间戳的规则:

Rule #2 : String dates are suitable for display using the user's time zone and computations. They aren’t on UTC but generally include an offset.
规则2:字符串日期适合使用用户的时区和计算显示。 它们不在UTC上,但通常包含偏移量。

在服务器端使其保持最新状态 (Keep it on date on the server side)

The rule about timestamps still applies on the server side. However the second rule about using string dates can’t be used.

关于时间戳的规则仍然适用于服务器端。 但是,不能使用有关使用字符串日期的第二条规则。

Indeed, in some case with technologies such as PHP, Java, and Rails the pages are rendered on server side (). This means all the HTML is generated by the server and it has no idea about the client's time zone. Think about the server – it’s nothing more than a computer on the globe. It also has its own time zone but it’s not necessarily the same as the client's time zone.

确实,在某些情况下,使用PHP,Java和Rails之类的技术,页面是在服务器端( )上呈现的。 这意味着所有HTML都是由服务器生成的,并且不了解客户端的时区。 考虑一下服务器–它只不过是全球的一台计算机。 它也有自己的时区,但不一定与客户的时区相同。

Rule #3 : Servers might either know the client's time zone or send a date on UTC. The server's time zone doesn’t matter.
规则3:服务器可能知道客户端的时区,也可能在UTC上发送日期。 服务器的时区无关紧要。

The new Java 8 Date/Time is considered one of the most understandable and clear APIs that helps you deal with date. I’m not going to explain how it works here but let’s review some interesting points.

新的Java 8日期/时间被认为是可帮助您处理日期的最易理解和最清晰的API之一。 在这里我不会解释它是如何工作的,但是让我们回顾一些有趣的观点。

LocalDateTime, OffsetDateTime and ZonedDateTime are the 3 classes provided to compute and display date and time. No more Date or DateTime which mix up displaying the local date and UTC date.

LocalDateTimeOffsetDateTimeZonedDateTime是提供用于计算和显示日期和时间的3个类。 没有更多的DateDateTime混淆了显示本地日期和UTC日期。

The following examples are extracted from (written by Jonas Konrad) which describes the Java 8 Date/Time API with a bunch of examples. By the way, many thanks to him, he kindly let me quote its pieces of code!

以下示例摘自 (由Jonas Konrad撰写),其中描述了Java 8 Date / Time API以及大量示例。 顺便说一句,非常感谢他,他让我引用了其中的代码!

Let’s look at the differences between the 3 classes:

让我们看一下这三个类之间的区别:

There is a small but important difference between OffsetDateTime and ZonedDateTime, did you notice it?

OffsetDateTimeZonedDateTime之间有一个小但重要的区别,您注意到了吗?

As its name says, OffsetDateTime is only aware of an offset between the local date and UTC. This means that it handles DST differently from a date which is attached to a time zone.

顾名思义, OffsetDateTime仅知道本地日期和UTC之间的偏移量。 这意味着它对DST的处理不同于附加到时区的日期。

The example with a time zone seems to be the right behavior. Actually, both are correct because adding 1 day can either mean:

具有时区的示例似乎是正确的行为。 实际上,两者都是正确的,因为增加1天可能意味着:

  • Add 1 day and keep the same hour (handles DST with ZonedDateTime)

    添加1天并保持同一小时(使用ZonedDateTime处理DST)

  • Add 24 hours to the current date (with OffsetDateTime).

    将当前时间增加24小时(使用OffsetDateTime )。

Remember Rule #1 about timestamps? You should only use a UTC timestamp for saving. The Java API provides an Instant class which is a timestamp you can get from any of the three classes used for displaying the date.

还记得有关时间戳的规则#1吗? 您只应使用UTC时间戳进行保存。 Java API提供了一个Instant类,这是一个时间戳,您可以从用于显示日期的三个类中的任何一个中获取时间戳。

最后的想法 (Final thoughts)

In this article, you've learned that timestamps are for saving (Rule #1) and string dates are for displaying (Rule #2). Did you notice that the number of seconds from the epoch is quite a big number?

在本文中,您了解了时间戳用于保存(规则1),字符串日期用于显示(规则2)。 您是否注意到距纪元的秒数​​很大?

That’s why after the comes the which stands for the year 2038. At 2038-01-19T03:14:07Z the timestamp (in seconds) will reach its maximum for 32-bit signed integers 2,147,483,647 . It will then turn into a negative number after adding one more second.

这就是为什么在出现 ,代表2038年的 。在2038-01-19T03:14:07Z ,时间戳(以秒为单位)将达到32位有符号整数2,147,483,647 。 再加上一秒钟后,它将变为负数。

‌On forums, people say they don’t care because their software won't be used for 20 years without re-writing. Well, that might be true but let’s still think about some solutions (with MySQL):

forum在论坛上,人们说他们不在乎,因为如果没有重写,其软件将无法使用20年。 好吧,这可能是对的,但让我们仍然考虑一些解决方案(使用MySQL):

  • Update TIMESTAMP type to 64-bit signed integers

    TIMESTAMP类型更新为64位有符号整数

  • Save UTC dates in DATETIME columns instead of TIMESTAMP

    将UTC日期保存在DATETIME列而不是TIMESTAMP

Both solutions have their advantages and drawbacks. The first one seems like a hack which reports the issue later. Yet, it fixes the issue for a very, very long time. Your software will be deprecated and not used anymore when the problem occurs again.

两种解决方案都有其优点和缺点。 第一个似乎是黑客,后来报告了该问题。 但是,它可以在很长一段时间内解决此问题。 当问题再次出现时,您的软件将被弃用且不再使用。

The second solution works for an almost infinite amount of time (up to 9999-12-31T23:59:59Z).

第二种解决方案可以工作几乎无限的时间(最多9999-12-31T23:59:59Z )。

Using TIMESTAMP is recommended for logs, while DATETIME is better for other needs. Remember a timestamp can’t store a date prior to 1970-01-01T00:00:00Z and not after 2038-01-19T03:14:07Z. This means you should use DATETIME to save dates far in the past and future.

建议将TIMESTAMP用于日志,而将DATETIME用于其他需求则更好。 请记住,时间戳记不能存储1970-01-01T00:00:00Z之前的日期,也不能存储2038-01-19T03:14:07Z之后的2038-01-19T03:14:07Z 。 这意味着您应该使用DATETIME保存过去和将来的日期。

Besides, in MySQL TIMESTAMPs are stored at UTC but displayed according to a specified time zone (and converted to UTC before saving). This mechanism comes in handy when you need to get a local date and doesn’t exist with DATETIME.

此外,在MySQL中, TIMESTAMP是存储在UTC处的,但根据指定的时区显示(并在保存之前转换为UTC)。 当您需要获取本地日期并且DATETIME不存在该机制时,此机制非常有用。

A last word about , a popular library to deal with dates. I first experimented an issue and wanted to warn you about it:

最后一点有关 ,这是一个处理日期的流行库。 我首先尝试了一个问题,并想警告您:

Both console.logs will output 2020-08-02 00:00. If you’re used to functional programming, you expect hours and minutes to return a new moment object because they are . It’s not the case – they modify the input date and return it for easy chaining.

两个console.log都将输出2020-08-02 00:00 。 如果您习惯了函数式编程,那么您期望hoursminutes返回一个新的moment对象,因为它们是 。 并非如此-他们修改了输入日期并返回它以便于链接。

Thanks for reading up to the end. I hope this experience of mine has been useful to you. By the way, I’m not very confident about the choice between TIMESTAMP and DATETIME, so don’t hesitate to share your experience!

感谢您阅读全文。 希望我的经验对您有所帮助。 顺便说一句,我对TIMESTAMPDATETIME之间的选择不是很自信,所以不要犹豫,分享您的经验!

If you found this article useful, please share it on social media to help others find it and to show your support! 👊

如果您觉得这篇文章很有用,请在社交媒体上分享它,以帮助其他人找到它并表示支持! 👊

Don’t forget to check my for upcoming articles 🙏

别忘了在我的查看即将发表的文章 🙏

翻译自:

ntp时间同步会同步时区吗

转载地址:http://vhgwd.baihongyu.com/

你可能感兴趣的文章
Android Studio-—使用OpenCV的配置方法和demo以及开发过程中遇到的问题解决
查看>>
第2天线性表链式存储
查看>>
python自动化测试-D11-学习笔记之一(yaml文件,ddt)
查看>>
mysql存储过程使用游标循环插入数据
查看>>
Ubuntu 12.04 添加新用户并启用root登录
查看>>
20145309信息安全系统设计基础第9周学习总结上
查看>>
c# 字段、属性get set
查看>>
td内容超出隐藏
查看>>
Spring CommonsMultipartResolver 上传文件
查看>>
Settings app简单学习记录
查看>>
SQLAlchemy
查看>>
多线程
查看>>
使用缓存的9大误区(下)转载
查看>>
appium键值对的应用
查看>>
MyEclipse 8.X 通用算法
查看>>
selenium.Phantomjs设置浏览器请求头
查看>>
分布式数据库如何选择,几种分布式数据库优缺点一览
查看>>
BZOJ 4443: 小凸玩矩阵【二分图】
查看>>
苹果 OS X制作u盘启动盘
查看>>
Jquery便利对象
查看>>