如何在我的应用程序中正确处理闰秒

时间:2016-06-22 16:19:36

标签: javascript php c time leap-second

我正在创建应用程序,我想知道如何我应该/可以处理闰秒。我试着用(希望)简单的示例情况来描述问题。在这种简单的情况下,你可以轻易地争辩说,每个+ - 1。5年的额外等待时间可能没有多大关系,但是我知道它能正常工作/我想要它的方式仍然会更好地睡觉所有'所有'情况:)

情况

(我们不会考虑任何延迟,因此当用户按下按钮时会立即发生

你有一个游戏,你可以在其中创建士兵。

  • 每位士兵需要110秒才能创作。
  • 用户按下按钮可在day 1 - 23:58:30
  • 创建1名士兵
  • 然后,用户希望稍后创建士兵110s。通过正常的日期时间计算'您的申请最终会以day 2 - 00:00:20
  • 结束

现在day 1day 2之间恰好有闰秒 - > 23:59:60。按照这种方法,用户实际上已经为他的士兵等待111s

我更喜欢使用Unix时间。这样,您只需将110s添加到当前时间(以秒为单位)。但据我所知,这也没有考虑到闰秒。您仍然在实际时间内等待111s

问题

我应该怎样做以确保用户或程序只等待它应该等待的时间?

是否有一个常用的时间戳确实考虑了闰秒?

我是否应该经常检查闰秒是否正在发生? (可能导致很多"腰部和#34;的cpu电源?)

编辑: 我主要使用Javascript(Node.js),但C,php或Python中的一个例子也可以正常工作!

4 个答案:

答案 0 :(得分:3)

UTC时间与原子时间的不同之处在于精确的闰秒。如果没有引用原子时间,则只能在插入闰秒时检测到UTC。这使得UTC中的时间“几乎”连续,因为这些小跳跃超过0.5秒且小于1.0秒,恰好在发生时打扰时间。 UTC被定义为保存日历时间并将其与地球运动相匹配,但尽管如此,只需忽略这些闰秒就可以认为它是连续的。

当插入闰秒时,您只需记下时钟中的任何内容,因为只有原子到utc时钟差异已得到纠正。只有在你计算行星或卫星轨道的情况下,你必须纠正到原子钟,或者你将在计算中插入整个leapsecond(并使你的轨道改变)实际效果是UTC已提前一秒一个幽灵。这只会影响秒数,在原子时间和UTC之间的差异会再次失去一秒。但是你注意到你的机器上没有发生任何事情。碰巧与闰秒发生重叠的时间戳的实时差异不受影响,因为闰秒插入仅影响原子秒和utc秒的编号差异。

如果您考虑时间与闰秒重叠(例如,在一些外星载体的轨道参数的微积分中),那么您必须花费额外的秒数(原子钟尚未计算)和UTC时间中的是)并将其添加到间隔,否则您的微积分将是不正确的。但是天体物理学总是使用正确的时间尺度进行微积分,所以不要犹豫是否误将空间垃圾掉在了头上。

如果您使用时钟同步程序(例如ntpd),那么插入闰秒可能会以多种方式发生:

  • 第二个插入是通过在跳跃时钟插入时将一个加到系统时钟来插入的。这会让奇怪的事情发生,因为这些时间的超时延迟会受到时钟调整的严重影响。

  • 时钟在闰秒之前的某个时间快速调整(假设前两个小时),并在闰秒后的某个时间再次调整正常。你将有一个连续的时间尺度,持续时间比标准原子时间略小于调整时间。

  • 让时钟运行。时钟循环突然“看到”参考(“新”utc标度)与其内部时钟之间的一秒偏移,因此它开始以正常方式校正它(调整时钟速度)。这与前一个相同,但会导致更多的偏移差异(前一个点整数秒为一半)

此时我不知道您的时钟同步应用程序是遵循第一种还是第二种方法。至少在linux中我认为使用的是第二个或第三个,通常你没有注意到它。

在你举例的情况下,并假设最坏的情况(通过在时钟中进行步调整来同步时间)你将获得在111s而不是110s创建的士兵,但是没有什么可担心的,因为那次失误中的一切发生在111s而不是110.你将获得1.0%更多的时间来获得你的士兵,但一切都发生了1.0%慢了在同一时期,你的士兵没有在闰秒之前或之后碰巧被怀孕的其他士兵的实际惩罚。

最后,如果你不使用时间同步程序,你的时钟将受到更大的影响,因为它的实际偏移量(你的时钟与实际时间的差异),而不是从对它进行步调整的漂移。 / p>

答案 1 :(得分:2)

你真的应该在这里使用时间戳。

时间戳只是从预定义日期(称为" epoch")的秒数(所有秒数,不是跳跃或不跳跃)。它只是一个柜台。

它不受闰秒,夏季/冬季时区变化的影响,甚至是每年改变时区边界的疯狂政府。

使用时间戳,您始终可以计算出UTC,GMT和欧洲/莫斯科的现在时间(闰秒,而不是它们,取决于您的tz_data配置)。反向操作有时无法做到。

答案 2 :(得分:2)

你不能在javascript中这样做。 javascript中没有闰秒。 ECMAScript 5,第15.9.1.1节说:

  

自UTC时间1970年1月1日起,时间以ECMAScript为单位,以毫秒为单位。在时间值中,忽略闰秒。假设每天恰好有86,400,000毫秒

时间值不保证是单调的,当闰秒发生时,它们很可能不会。在POSIX中,您可以clock_gettime使用clk_id CLOCK_MONOTONIC(如果已定义_POSIX_MONOTONIC_CLOCK)。

答案 3 :(得分:0)

有些RTL支持闰秒。例如,在Ada 2005中,Ada.Calendar.Time支持闰秒,虽然不是很明显,但只能通过子包Ada.Calendar.Formatting and Ada.Calendar.Arithmetic进行观察。此外,Ada.Calendar.Formatting.Image写道":59"闰秒和Ada.Calendar.Formatting.Value不接受":60"。

在没有原生闰秒支持的the GNAT目标中需要" -y"用于打开它的活页夹键。有了这把钥匙,我甚至在Windows上设法使用闰秒时间。我已经tiny library for conversion from UNIX time_t with or without leap seconds, and also formatting/parsing functions supporting leap seconds完全公开了Ada标准的这个功能。当然,在Windows上,第二阶段的不一致性是不可避免的,但可以正确计算时刻之间的差异,并且可以对从其他地方获得的值进行操作。

应该使用

Monotonic time来避免在此过程中的冲击。无论如何都应该使用它,因为用户可以改变时钟时间,或者可以通过同步来调整时间,这种情况发生得更频繁,而且比闰秒更难以预测。

如果你真的需要这个,你可以使用单调时间来推断平民:

with Ada.Calendar;
with Ada.Real_Time;

-- ...

------------------------
-- Extrapolated_Clock --
------------------------

type Extrapolated_Clock is tagged record
   C_Clock : Ada.Calendar.Time := Ada.Calendar.Clock;
   RT_Clock : Ada.Real_Time.Time := Ada.Real_Time.Clock;
end record;

use all type Ada.Calendar.Time;
use all type Ada.Real_Time.Time;
use all type Ada.Real_Time.Time_Span;

procedure Synchronize (Object : in out Extrapolated_Clock);
function Extrapolate (Object : Extrapolated_Clock) return Ada.Calendar.Time is
  (Object.C_Clock + To_Duration (Ada.Real_Time.Clock - Object.RT_Clock));

-- ...

------------------------------------
-- Extrapolated_Clock.Synchronize --
------------------------------------

procedure Synchronize (Object : in out Extrapolated_Clock) is
begin
   Object.C_Clock := Ada.Calendar.Clock;
   Object.RT_Clock := Ada.Real_Time.Clock;
end Synchronize;

您可能还需要确保捕获的时刻不会是闰秒(捕获的时间之后的第二个不是跳跃)。