首先,请认识到,在现代术语中,你应该说UTC而不是GMT.它们基本上是等价的,只是UTC的定义更精确.保留GMT一词,以指英国在冬季月份生效的时区中UTC+0偏移部分.
现在来回答你的问题.UTC不一定是存储所有日期和时间值的最佳方式.它对past项赛事或future absolute项赛事特别有效,但对future local项赛事——尤其是future recurring项赛事——效果不太好.
我最近写了关于这on another answer的文章,这是当地时间比UTC更有意义的少数例外情况之一.主要论点是"闹钟问题".如果您将闹钟设置为UTC,则在DST转换当天,您将早起或晚起一小时.这就是为什么大多数人按当地时间设置闹钟.
当然,如果你使用的是来自世界各地的数据,你就无法存储一个本地时间.你应该储存一些不同的东西:
- 重复事件的本地时间,例如"08:00"
- 表示当地时间的时区,如"美国/纽约"
- 重复模式,以任何对应用程序有意义的格式,例如每天、每两周或每月的第三个星期四等.
- 下一个immediate UTC的日期和时间,尽你所能预测.
- 也许,但并非总是,future 事件UTC日期和时间的列表,将某个预定义的时间段投射到future (可能是一周,可能是6个月,可能是一年或两年,取决于您的需要).
对于后两种情况,请理解,如果负责该时区的政府决定更改任何内容,则与任何本地日期/时间相当的UTC时间可能会更改.因为每年都有多个时区数据库更新,所以你需要有一个定期更新subscribe to announcements of updates和update your timezone database的计划.无论何时更新时区数据,都需要重新计算所有future 事件的UTC等效时间.
如果您计划显示跨越多个时区的任何类型的事件列表,使用UTC等效值非常重要.这些是您将查询以构建该列表的值.
另一点需要考虑的是,如果一个事件被安排在DST回落过渡期间发生的本地时间,则必须决定事件是否发生在第一个实例(通常)、或第二个实例(有时),或者两者都(很少).并在应用程序中构建一种机制,以确保事件不会触发两次,除非您愿意.
如果你在寻找一个简单的答案——对不起,没有.跨时区安排future 事件是一项复杂的任务.
Alternative Approach
我让一些人向我展示了一种技术,他们do使用UTC时间进行日程安排,即他们 Select 当地时间的开始日期,将其转换为UTC进行存储,并存储时区ID.然后在运行时,他们应用时区将原始UTC时间转换回本地时间,然后使用该本地时间计算其他重复出现的时间,就好像它是最初按上述方式存储的时间一样.
虽然这项技术可以达到work%,但缺点是:
如果在第一个实例运行之前有一个时区更新更改了本地时间,那么它将取消整个时间表.这可以通过为"第一"实例 Select 过go 的时间来缓解,这样第二个实例实际上就是第一个实例.
如果时间真的是一个"浮动时间",应该跟随用户四处移动(比如在手机上的闹钟中),那么你仍然需要存储最初创建它的区域的时区信息——即使那不是你想要运行的区域.
它增加了额外的复杂性,但没有任何好处.我将保留这项技术,以便在您可能有一个仅适用于UTC的调度器的情况下,try 将时区支持 retrofit 为该调度器.