本文共 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.
这对我来说是一个学习如何正确处理国际软件日期和时间的机会。 在本文中,我将介绍时区问题并分享一些要遵循的规则。
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
),并且容易出错。 例如,尽量不要混淆Arab
, Arabic
和Arabian 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
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
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上,但通常包含偏移量。
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.
LocalDateTime
, OffsetDateTime
和ZonedDateTime
是提供用于计算和显示日期和时间的3个类。 没有更多的Date
或DateTime
混淆了显示本地日期和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?
OffsetDateTime
和ZonedDateTime
之间有一个小但重要的区别,您注意到了吗?
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
类,这是一个时间戳,您可以从用于显示日期的三个类中的任何一个中获取时间戳。
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 TIMESTAMP
s 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.log
s 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
。 如果您习惯了函数式编程,那么您期望hours
和minutes
返回一个新的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!
感谢您阅读全文。 希望我的经验对您有所帮助。 顺便说一句,我对TIMESTAMP
和DATETIME
之间的选择不是很自信,所以不要犹豫,分享您的经验!
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/