处理存储中的时区?
将所有内容存储为 GMT?
按照嵌入偏移量输入的方式存储所有内容?
每次渲染时都进行数学计算吗?
显示相对时间“1 分钟前”?
Store everything in GMT?
Store everything the way it was entered with an embedded offset?
Do the math everytime you render?
Display relative Times "1 minutes ago"?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
日期应存储为 UTC 除非它是用户提供的数据,并且您无法知道用户希望该数据位于哪个时区。有时(非常罕见)您只需要存储小时、分钟、秒、日、月和年组件没有任何时区,因此您可以将其返回给用户。 现在,对于新开发人员或者如果您不确定,请存储 UTC,您的正确率将达到 99%。
但不要误以为这对于所有情况都 100% 有效。 它不是。
Dates should be stored as UTC UNLESS it is user provided data and you CANNOT know what timezone the user intended that data to be in. Sometimes (very very rarely) you need to just store the hour, minute, second, day, month and year components without any timezone so you can spit it out back to the user. Now for new developers or if you're unsure, store UTC and you will be 99% correct.
But don't be fooled by believing this works 100% of the time for all cases all the time. It does not.
我通常只使用 Unix 时间。 未来不一定安全,但效果很好。
I usually just use Unix time. not necessarily future safe, but it works pretty well.
始终以 GMT(或 UTC)存储。 从那里可以轻松转换为任何本地时区值。
Always store in GMT (or UTC). From there it is easy to convert to any local time zone value.
对我来说,以 GMT/UTC 存储所有内容似乎最合乎逻辑。 然后,您可以显示所需的每个时区的日期和时间。
一些注意事项:
挂钟时间,那就是
主导代表,那么就是
不是一个绝对指定的时间。
你应该(并且不能)转换它
在任何 GMT 表示形式中。 上午 9:00
每天早上。 换句话说:
这不是(日期)时间。
保存未来的日期和时间
预约时,您应该使用
由输入指定的 GMT 偏移量
时区和时刻
本身。。 所以如果这是一个约会
夏天在冬天制作,例如
西欧,时间为 +2:00,
尽管正常(冬季)
偏移量为+1:00。 这将解决
Bwooce 的压延机问题
提及。
这适用于使用权利
转换为 GMT 时的偏移量
当转换回 a 时适用
任何特定的日期和时间
时区。
幸运的是,如果使用正确,(.NET) DateTime 类型会为您处理保存日历等的所有细节,并且当您知道它如何工作时,所有这些都应该非常容易。
Storing everything in GMT/UTC seems most logical to me. You can then show the date and time in every timezone you want.
A few ceveats:
wall clock time and that is the
leading representation, then it is
not an absolutely specified time.
You should (and cannot) convert it
in any GMT representation. E.G. 9:00
AM every morning. In other words:
this is no (date)time.
save a date and time of a future
appointment, you should use the
offset to GMT specified by the input
timezone and the the moment in time
itself. So if it is an appointment
in summer made in winter in e.g.
western europe, it is +2:00,
allthough the normal (winter time)
offset is +1:00. This will solve the
calender problem that Bwooce
mentioned.
that applies to using the right
offset while converting to GMT
applies when converting back to a
date and time in any particular
timezone.
Luckily, when used correctly, the (.NET) DateTime type takes care of all the gory details of keeping calendars etc. for you and all of this should be very easy when you know how it works.
所以我用 MSSQL 服务器做了一个小实验。
我创建了一个表并添加了一行包含当前本地时区(澳大利亚)的行。
然后我将日期时间更改为 GMT 并添加了另一行。
尽管这些行是相隔大约 10 秒添加的,但它们在 SQL Server 中显示的时间间隔却是相隔 10 小时。
如果不出意外,它至少告诉我应该以一致的方式存储日期,这对我来说,增加了将日期存储为 GMT 的论点。
So I ran a little experiment with MSSQL server.
I created a table and added a row with the current localized timezone (Australia).
Then I changed my datetime to be GMT and added another row.
Even tho those rows were added around 10 seconds apart, they appear in SQL server as tho they're 10 hours apart.
If nothing else, it at least tells me that I should be storing dates in a conisitent manner, which for me, adds weight to the argument for storing them as GMT.
就我个人而言,我看不出有什么理由不将所有内容存储在 GMT 中,然后使用用户本地时区来显示与他们相关的时间。
如果你想显示相对时间,显然你仍然需要时间并进行翻译,但如果你确实想进行翻译,我认为 GMT 仍然是你最好的选择。
Personally, I can't see any reason not to store everything in GMT and then use the users local timezone to display the time as it relates to them.
If you want to display relative time, you obviously still need the time and do a translation, but if you do want to do the translation I think GMT is still your best option.
我喜欢以 GMT 格式存储并仅显示相对时间(“大约 10 秒前”、“5 个月前”)。 对于大多数用例,用户不需要查看实际时间戳。
当然也有例外,并且单个应用程序可能有很多例外,因此它不可能是“单向”答案。 需要强大审计能力的事物(例如投票)以及时间是讨论领域一部分的系统(天文学、科学研究)可能需要向用户显示真实的时间戳。
不过,大多数应用程序通过简单的相对时间更容易理解。
I like storing in GMT and showing only relative ("about 10 seconds ago", "5 months ago"). Users don't need to see actual timestamps for most use cases.
There are certainly exceptions, and an individual application might have many of them, so it can't be a 'one-true-way' answer. Things that need strong audit-ability (e.g. voting), and systems where time is part of the domain of discourse (astronomy, scientific research) might demand true timestamps to be shown to the user.
Most apps, though, are easier to understand with a simple relative time.
乔什在上面完全正确,但我有一个微妙的警告需要解释。 这是一个关于未来事件和时区没有正确答案的案例。
考虑重复约会的情况。 它发生在 GMT 0000(为简单起见),即 NZST(新西兰标准时间)1200 点和澳大利亚悉尼 AEST 1000 点。
当夏令时在某一区域生效时,预约会发生什么情况? 是否应该:
1a。 如果 TZ 变化位于
约会的“所有者”(谁
预订了)然后尝试留在
相同的桌面时钟时间(例如上午 10:00)?
1b. 如果
TZ 更改位于其中之一
会议参加者的区域然后没有
改变的
后果:它的移动是为了
其他所有人都出乎意料地由于
所有者 TZ 发生了变化,但它仍然存在
“上午 10 点会议”
业主很关心。
'2. 如上所述,但相反。
后果:会议所有者发生变化(上午 10 点的会议变成上午 9 点的会议,或 v/v),这可能是预料之中的,但不方便。 对于其他与会者来说,它保持相同的桌面时钟时间,直到他们完成自己的 TZ 转换。
两者都不完美。 考虑两次约会的情况,一次由 A 预订,发生在当地时间上午 10 点,另一次由 B 预订,A 作为与会者,发生在上午 9 点。 如果 A 和 B 位于不同的 TZ,那么 DST 更改很容易导致他们被重复预订。
如果此时你的想法有点偏执,那么我很理解。
这个例子背后的要点是,要正确执行这些行为,您不仅需要知道当地时间的 UTC 版本,还需要知道所有者预订时所在的 TZ(而不是偏移量)。 否则你别无选择,只能默默地采取选项 2,甚至不通知任何人事情发生了变化,因为 GMT 时间没有改变,只有演示文稿发生了变化......对吗? (不,这是陷阱,当上午 10 点的会议自行进行时,演示很重要)
我必须感谢我的同事兼朋友杰森·波洛克(Jason Pollock)的这一见解。 阅读这里的观点,以及后续内容讨论 iCal 和 VTIMEZONE 在这里。
Josh is completely correct above, but I have one subtle caveat to explain. This is a case with no correct answer regarding future events and timezones.
Consider the case of a repeating appointment. It occurs at GMT 0000 (for simplicity), which is 1200 NZST (New Zealand Standard Time) and 1000 AEST in Sydney Australia.
When Daylight Savings comes into effect in one zone, what should occur to the appointment? Should it:
1a. If the TZ change is in the zone of
the appointment's "owner" (who
booked it) then attempt to remain at
the same desk clock time (eg 10:00am)?
1b. If the
TZ change is in one of the other
meeting attendee's zones then no
change
Consequences: It moves for
everyone else, unexpectedly, due to
the owners TZ change, but it stays
"the 10am meeting" as far as the
owner is concerned.
'2. As above, but reversed.
Consequences: It moves for the meeting owner (the 10am meeting becomes the 9am meeting, or v/v), which may be expected but inconvenient. It stays at the same desk clock time for the other attendees until they go through their own TZ transition.
Neither is perfect. Consider the case of two appointments, one booked by Person A that occurs at 10am local time, the other booked by Person B with Person A as an attendee that occurs at 9am. If Person A and Person B are in different TZ's then a DST change could easily cause them to become double-booked.
If your mind is a bit bent at this point then I quite understand.
The point behind this example is that to do either of these behaviors properly you need to know not just the UTC version of the local time, but the TZ (and not the offset) that the owner was in when they booked it. Otherwise you have no choice but to take option 2, silently, without even informing anyone that things have changed since GMT times don't change and only the presentation changes...right? (no, this is the trap, presentation matters when your 10am meeting moves by itself)
I have to credit my colleague and friend Jason Pollock for this insight. Read his view here, and the follow-up discussing iCal and VTIMEZONE here.
MS Dynamics 存储 GMT,然后在用户级别了解您相对于 GMT 的时区。 然后它会向您显示您所在时区的项目。
只是想我会把它扔掉,因为微软有一个相当大的团队,这就是他们决定处理它的方式。
MS Dynamics stores GMT and then at a user level knows your times zone relative to GMT. Then it displays items to you in your time zone.
Just thought I'd throw that out there as that's a pretty big group at MS and this is how they decided to handle it.
我更喜欢用时区存储所有内容。
客户可以决定稍后以哪种方式呈现。
我最喜欢的转换库是 PostgreSQL-Database。
i prefer to store everything with the timezone.
the client can decide, which way it should be presented later.
my favorite library for converting is the PostgreSQL-Database.
看看这里,w3c 已经很好地回答了这个问题。
查看用例。
http://www.w3.org/TR/timezone/
请注意,他们建议存储日期时间由于 UTC 而非 GMT,GMT 受夏令时约束。
Have a look here, the w3c have done an excellent job answering the question.
Look at the use cases.
http://www.w3.org/TR/timezone/
Note that they recommend storing datetimes as UTC not GMT, GMT is subject to daylight savings time.
一如既往,答案是“取决于”。
这取决于您所描述的时间以及数据是如何提供给您的。
决定如何存储时间值的关键是确定是否会因删除时区而丢失信息,以及不要让用户感到惊讶。
在 UTC time_t 中存储数据有明显的好处 - 它是单个 int,允许快速排序和轻松存储。
我认为这个问题被分解为特定的领域:
每个领域都有以下子类:
让我们一次看一个。
系统提供:我建议在 UTC 中运行系统,这样就可以避免时区问题,并且不会出现任何信息丢失(始终是 UTC)。
历史数据:这些是系统日志文件、进程统计信息、跟踪、评论日期/时间等。数据不会更改,时区描述符也不会追溯更改。 对于此类数据,无论提供的时区如何,以 UTC 存储信息都不会丢失任何信息。因此,请删除时区。
未来的长期数据:这些事件要么是遥远的未来,要么将继续发生。 如果它们保留足够长的时间,时区描述符一定会发生变化。 此类数据的一个很好的例子是“每周管理会议”。 这是输入一次的数据,预计将永久有效。 对于这些值,确定它是系统提供的还是用户提供的非常重要。 对于用户提供的数据,时间应与创建者的时区一起存储,其他任何情况都会导致信息丢失。 当时区定义发生变化并且向创建者显示的时间具有完全不同的值时,这种信息丢失就会变得明显!
正如 Bwooce 所指出的,创作者和观众位于不同时区,这会造成一些混乱。 在这种情况下,我希望应用程序能够指示哪些时间值由于时区与之前位置的变化而发生了移动。
未来短期数据:这些数据很快就会成为历史数据,或者仅在短时间内有效。 示例可以是间隔计时器、评级转换等。对于此数据,由于定义在值的创建和成为历史的时间之间发生变化的可能性很低,因此可能无需删除时区。 然而,我发现这些值有一个坏习惯,会成为“未来的长期数据”。
一旦决定存储时区,就必须注意它的存储方式。
如果您将时区存储为偏移量,那么如果时区发生变化,您会怎么做? 您是否检查系统并对现有数据进行全面更改? 如果这样做,那么您现在就已经将所有历史值弄错了。 Oracle 和 iCal 就是这种错误的典型例子。 Oracle 将时区信息存储为与 UTC 的偏移量,iCal 包含创建时区的完整描述符。
这允许更改时区的定义,而无需修改现有值。 它确实使排序变得更加困难,因为如果时区数据发生更改,生成的任何索引都可能无效。
如果开发人员继续以 UTC 存储所有内容,而不管时区如何,我们将继续看到上一批时区更改中出现的问题。
在一个组织中,秘书们必须在夏令时之前为其团队打印日历,然后在更改后再次打印。 最后,他们对两者进行了比较,并重新创建了所有已移动的约会。 当然,他们错过了几个,并且有几个星期的痛苦,直到旧的夏令时日期到来并且时间再次变得正确。
The answer, as always, is "depends".
It depends on what you are describing with the time, and how the data was provided to you.
The key to deciding how to store time values is deciding if you are losing information by dropping the timezone, as well as not surprising your users.
There are definite benefits in storing data in a UTC time_t - it is a single int, allowing quick sorting and easy storage.
I see the problem as being broken down into specific areas:
With the following subclasses on each:
Let's look at them one at a time.
System Provided: I would recommend running systems in UTC, then you avoid the timezone problem and again, no information loss is seen (it's always UTC).
Historical Data: These are things like system log files, process statistics, tracing, comment dates/times, etc. The data isn't going to change, and the timezone descriptor isn't going to change retroactively. For this type of data, there is no information lost by storing the information in UTC regardless of the timezone it was provided in. So, drop the timezone.
Future, Long Term Data: These are events that are either far enough in the future or will keep happening. If they are kept around long enough, the timezone descriptors are guaranteed change. A good example of this type of data is, "The Weekly Management Meeting". This is data that is entered once, and expected to keep working into perpetuity. For these values, it is important to determine if it is system or user provided. For user-provided data, the time should be stored with the creator's timezone, anything else results in information loss. This information loss becomes apparent when the timezone definition changes and the time is displayed to the creator as having an entirely different value!
As Bwooce has indicated, there is some confusion where the creator and viewer are in different timezones. In that case, I would expect the application to indicate which time values have moved due to a timezone shift from their previous locations.
Future, Short Term Data: This is data that is quickly going to become historical, or is only valid for a short period of time. Examples could be interval timers, rating transitions, etc. For this data, since the likelihood is low that the definition will change between the creation of the value and the time it becomes historical, it might be possible to get away with dropping the timezone. However, I have found that these values have a bad habit of becoming "Future, Long Term Data".
Once you have decided to store the timezone, care must be taken with how it is stored.
If you store a timezone as an offset, what do you do if the timezone changes? Do you go through the system and do a blanket change on the existing data? If you do, you've now made any historical values incorrect. Good examples of this fault are Oracle and iCal. Oracle stores timezone information as an offset from UTC, and iCal includes the full descriptor for the creation timezone.
This allows the definition of the timezone to change without having to modify the existing values you have. It does make sorting more difficult, since any index that is generated may be invalid if the timezone data changes.
If developers continue to store everything in UTC, irrespective of timezone, we will continue to see the problems that we've seen with the last batch of timezone changes.
At one organisation, the secretaries had to print out the calendars for their teams before the daylight savings date, and then print them out again after the change. Finally, they compared the two and re-created all of the appointments that had moved. Of course, they missed several, and there were several weeks of pain until the old daylight savings date was reached and the times became correct again.
您必须以 UTC 存储 - 如果您不这样做,您在夏令时等情况下的历史报告和行为就会变得……有趣。 GMT 是当地时间,相对于 UTC 实行夏令时(但并非如此)。
如果您存储的是当地时间,那么向不同时区的用户进行演示可能会很糟糕。 如果您的原始数据采用 UTC 格式,则很容易调整为本地 - 只需添加用户的偏移量即可完成!
Joel 在一个播客中谈到了这一点(以一种迂回的方式)——他说要 存储你的尽可能高分辨率的数据(搜索“保真度”),因为当它再次熄灭时,您始终可以对其进行处理。 这就是为什么我说将其存储为 UTC,作为当地时间,您需要为不在该时区的任何人进行调整,这是一项艰巨的工作。 例如,您需要存储存储时间时夏令时是否有效。 哎呀。
过去我经常在数据库中存储两个 - UTC 用于排序,当地时间用于显示。 这样用户和计算机都不会感到困惑。
现在,至于显示:当然,您可以执行“3 分钟前”的操作,但前提是您存储 UTC - 否则,在不同时区输入的数据将执行诸如显示为“-4 小时前”之类的操作,这将把人们吓坏了。 如果您要显示实际时间,人们喜欢使用当地时间 - 如果数据是在多个时区输入的,则只有存储 UTC 时才能轻松做到这一点。
You have to store in UTC - if you don't, your historic reporting and behaviour during things like Daylight Savings goes... funny. GMT is a local time, subject to Daylight Savings relative to UTC (which is not).
Presentation to users in different time-zones can be a real bastard if you're storing local time. It's easy to adjust to local if your raw data is in UTC - just add your user's offset and you're done!
Joel talked about this in one of the podcasts (in a round-about way) - he said to store your data in the highest resolution possible (search for 'fidelity'), because you can always munge it when it goes out again. That's why I say store it as UTC, as local time you need to adjust for anyone who's not in that timezone, and that's a lot of hard work. And you need to store whether, for example, daylight savings was in effect when you stored the time. Yuk.
Often in databases in the past I've stored two - UTC for sorting, local time for display. That way neither the user nor the computer get confused.
Now, as to display: Sure, you can do the "3 minutes ago" thing, but only if you store UTC - otherwise, data entered in different timezones is going to do things like display as "-4 hours ago", which will freak people out. If you're going to display an actual time, people love to have it in their local time - and if data's being entered in multiple timezones you can only do that with ease if you're storing UTC.