[erlang-questions] microseconds since midnight

Henning Diedrich hd2010@REDACTED
Sun Jan 10 16:27:52 CET 2010

Hi Ulf,

thanks a lot for clarifying! I understood now, I think I'd disagree now 
on other grounds:

now() can't fall behind over midnight due to its internal format of Mega 
seconds. But it could happen to be behind universaltime() if there was a 
system time change.

But I am fine for what I wanted. I also changed the code as you 
suggested, as shown below. So for completeness, here are my thoughts, 
skip'em they might not be worth your time:

The intent was to have a reference tick for relative comparison. As the 
basis for approximation in an Internet scenario, with the clients having 
10-100ms latencies, so there can never be full synchronization but an 
understanding of the relative lag any package might have compared to the 
fastest package ever received before.

This will allow for time based corrections of information that are worth 
the effort even where they only yield something exact to some 
milliseconds. In occasional moments of congestion they will easily 
correct for >100ms and to catch these spikes was the main concern.

For this, the absolute offset itself is canceled out in the end and it's 
only important to have it constant. Which is why Jayson has a point that 
I might as well simply let the bytes roll over! But there was an 
agreement on a midnight protocol, so I am going for that for this iteration.

universaltime() and now() not being in sync could pose a 'thread' to the 
intended four byte format as that could result in negative or too high 
offsets. So this should be the safe implementation, like you suggested:

nightsynctime_offset() ->   
    {MegaSec, Seconds, _} = Now = now(),
    {_, Time} = calendar:now_to_datetime(Now),
    SecSinceMidnight = calendar:time_to_seconds(Time),
    % MidNightOffset =
    (MegaSec * 1000000) + Seconds - SecSinceMidnight.

But not because now() could be called after midnight, and universaltime 
before (making for a 24h gap). Because now() is not affected by midnight 
with it's megasecond format. But the nature of now that you pointed to 
may entail much more frequent and longer lasting cases where now() may 
be trailing universaltime so that to the contrary universaltime may be 
past midnight already and now still before, skewing the offset for 24h 
in the other direction?

Thank you for pointing out the better implementation. No matter how 
unlikely the cases might be, now it's right.

Your notes helped a lot getting a better understanding of the nature of 
now() and the other time functions.

Ulf Wiger wrote:
> Henning Diedrich wrote:
>> Hi Ulf,
>> As it is now, I don't poll time twice. But I depend on state,using a 
>> constant MidNightOffset.
> But you do check it twice:
>> nightsynctime_offset() ->
>>     {_, Time_1} = erlang:universaltime(),   %% <- HERE
>>     SSMN_1 = calendar:time_to_seconds(Time_1),
>>     {MegaSec_2, Seconds_2, _} = now(),      %% <- AND HERE
>>     % MidNightOffset =
>>     (MegaSec_2 * 1000000) + Seconds_2 - SSMN_1.
> Rather than first calling universaltime() and then calling now,
> call now() once, and then use calendar:now_to_datetime(Now) to
> derive the other representation from that one sample.
> When you run small-scale tests without load, you won't notice a
> difference, but on a heavily loaded system, the admittedly unlikely
> event that the process is scheduled out between the call to 
> universaltime() and the call to now() right around midnight, could
> well give you a situation where the universaltime() call shows
> {23,59,59}, while the now() call shows a time right after midnight.
> But as you also talked about sending these values to other nodes,
> you will of course also have to contend with the fact that the
> system clocks on different nodes can at best be sychronized to
> within a few ms using NTP. You should never rely on wall-clock
> time for synchronization across the network.
> But perhaps I misunderstood your intent?
> BR,
> Ulf W

More information about the erlang-questions mailing list