我正在寻找一些最佳实践来处理和存储静态时间值。
静态时间通常是重复活动的时间,例如体育中心的活动,餐厅的开放时间,电视节目每天播出的时间。
此时间值未绑定到特定日期,不应受夏令时的影响。例如,餐厅将在冬季和夏季的上午11:00开放。
处理这种情况的最佳方法是什么?如何存储这种价值? 我主要对自动TimeZone和DST调整(应该避免)的问题感兴趣,并且保持时间值独立于任何特定日期。
我到目前为止找到的最佳策略是:
我读过this question,但主要是关于正常时间值,而不是我描述的用例。
我正在处理的图书馆:github
答案 0 :(得分:2)
关于数据库存储,请按照从最优选到最不喜欢的选项的顺序考虑以下内容:
如果您的数据库支持,请使用TIME
类型,例如SQL Server(2008及更高版本),MySQL和Postgres,或Oracle中的INTERVAL HOUR TO SECOND
。
为小时和分钟使用单独的整数字段(如果需要,可以使用秒数)。如果您的数据库支持,请考虑使用自定义用户定义类型将它们绑定在一起。
使用带有前导零的24小时格式的字符串,例如"01:23:00"
,"12:00:00"
或"23:59:00"
。如果包含秒数,则始终包括秒数。您希望保持字符串按字典顺序排序。不要混合和匹配格式。保持一致。
关于存储从午夜起经过的整数分钟(或秒)的方法,我建议避免它。当你实际存储一段经过的时间时,这种方法很有用,但在存储一天的时间时效果不是很好。考虑:
不是每天都有午夜。在一些时区(例如巴西),在春季DST过渡的那天,时钟从23:59:59到01:00:00。
在拥有DST的任何时区中,"自午夜以来经过的时间"可能骗你。即使午夜存在,如果将10:00保存为" 10小时",那么这可能是错误的陈述。如果您考虑每年两天参与DST过渡,可能已经过了9个小时或11个小时,因为午夜过去了。
在您的应用程序中的某个时刻,您可能会将此时间值应用于某个特定日期。当你这样做时,如果你正在使用"经过时间"语义,您可能只想将经过的时间添加到相关日期的午夜。由于我刚才提到的原因,这将导致DST过渡日出错。如果您代表的是"时间"在您的存储空间中,您更有可能将它们正确地组合在一起。当然,这在很大程度上取决于您使用的语言和API。
使用其中任何一种,使用重复模式时要小心。假设您存储时间为" 02:00:00"当酒吧每晚关闭。当DST向前弹出时,该时间可能不存在,当它退回时,它将存在两次。当您将时间应用于任何特定日期时,您需要准备好检查这种情况。
您应该做的完全取决于您的使用案例。在许多情况下,明智的做法是在弹簧前进间隙中向前跳一小时,并在后退重叠中选择两个点中的第一个。但是YMMV。
另请参阅DST tag wiki。
根据评论,看起来the "tod" gem足以满足您的Ruby代码。
答案 1 :(得分:1)
问题似乎有点模糊,但我会试一试。
一般来说,使用整数对我来说似乎已经足够了。它易于比较,易于添加或减去持续时间(秒),并且节省空间和时间。如果使用面向对象语言,可以考虑将其包装在类中。
据我所知,在C或C ++中没有适合您需求的类。
在.NET世界中,TimeSpan
类可能对您有用。它有一些便利,例如:你可以从DateTime.TimeOfDay
获得TimeSpan值;您可以添加TimeSpan
间隔(TimeSpan
);你可以分别得到小时,分钟和秒组件;等
如果使用Python,datime.time
也是一个很好的候选者。它专为像您这样的用户设计。
我不知道其他语言的其他优秀候选人。
答案 2 :(得分:1)
为Java讲话:
在Java中,旧的java.util.Date
(尽管名称是全球时间戳)或java.util.GregorianCalendar
(这是日期和时间的组合)很好地涵盖了您描述的用例。时间和地区等),但是:
在Java 8中,您有新的内置类java.time.LocalTime
,它可以很好地覆盖您的用例。 Predecessor是外部流行的Java库JodaTime中同名的类LocalTime
,它从Java 5开始工作。此外,在我自己的alpha-state-library中,我有类型net.time4j.PlainTime
这是类似的,但也提供24:00支持(例如商店开放时间的好)。总而言之,Java是一种非常适合的语言,其中包含有趣的时间库,这些库可以完全按照您的意愿执详细说明:
a)TimeZone和DST调整不由上面提到的Java类处理。相反,只有将这样的普通墙时间转换为包含对时区的引用的org.joda.time.DateTime
这样的另一种类型时,才会处理它们。
b)确实,这些时间类也完全独立于日历日期。
c)内部存储策略适用于JSR-310(Java 8):
private final byte hour;
private final byte minute;
private final byte second;
private final int nano;
JodaTime使用本地毫秒的其他策略(自午夜起经过的时间)。
答案 3 :(得分:0)
除非您也知道日/月/年,否则您无法代表时间。没有"不应该受到夏令时的影响"因为有许多复杂的问题要处理,包括闰秒等。正如人类所看到的那样,时间是一件复杂的事情,无法用数学方法轻易处理。
如果你真的需要存储" 11 am"没有任何相关的日期,那么你应该存储什么。只需存储上午11点(或者只是11点,使用24小时)。
然后,如果您需要进行任何数学运算,您必须在执行任何操作之前应用日期。
我也不会存储" 11 am" as"从午夜开始的x秒"。你真的应该使用11个小时,因为这是用户看到的,然后有一个好的日期/时间库将其转换为有用的格式。例如,告诉用户餐厅现在是否开放,您可以将其传递到今天的日期库。