now() and arithmetic

Matthias Lang <>
Mon May 6 10:58:25 CEST 2002


 > Does TZ actually affect now() on some platforms? 

I think the manpage is wrong:

  now()

              Returns the tuple {MegaSecs, Secs, Microsecs}

              which  is the elapsed time since 00:00 GMT, January
              1, 1970 (zero hour) on  the  assumption  that  the
              underlying  OS supports this. Otherwise, some other
              point in time is chosen. It is also guaranteed that
              subsequent  calls  to this BIF returns continuously
              increasing values. Hence,  the  return  value  from
              now()  can  be used to generate unique time-stamps.
              It can only be used to check the local time of  day
              if  the  time-zone info of the underlying operating
              system is properly configured.

now() is defined as being the elapsed time since 00:00 GMT, Jan 1,
1970, so it should be independent of the timezone in any case. Maybe
the last sentence should be moved to the calendar module, under
now_to_local_time/1.

Digging deeper: the value now() returns is based on
sys_gettimeofday(), which, for all unix implementations, is a call to
gettimeofday with a NULL second argument. Under linux that means TZ
does not affect it. I'd be surprised if that wasn't so for other
unices. No idea what VxWorks and Windows do. As far as I can see
(quick look only!), the highres timer stuff in solaris is only used to
fine-tune the value from gettimeofday.

 > Is this the "rapidly changing system time" or have you had some 
 > crazy users playing with the time?

<war story>

Whenever one of Corelatus' magic boxes was newly installed and
configured in the customer's test lab, the internal hardware watchdog
would reboot it once. Embarassing when you're selling a 'carrier
class' system.

Turned out that all the systems had been sitting in storage for a
month and had thus forgotten what the time was (we use a high MTBF
'supercap' instead of a battery, so the realtime clock can keep going
for a week without power, but not a month). So, on first boot, they'd
get a hardcoded time and, as soon as NTP was configured, the system
time would adjust itself by about a year. Because of a bug in Erlang
R7B-3 (fixed in R8B-1), Erlang's timers would go insane and trigger
events nonstop. The VM's CPU use would be sky high, which the watchdog
correctly diagnosed as a sign of insanity and rebooted.

Now that the problem is fixed, the same series of events causes no
greater damage than now() running 1% faster than it really should, so
all of our internal timers are 1% shorter than nominal. Truly
timing-critical events are managed by hardware, so this is OK for us.

</war story>

 > PS Here are my amazingly simple routines.
 > 
 > now_to_timeval() ->
 >     now_to_timeval(now()).
 > 
 > now_to_timeval({MegaSecs, Secs, MicroSecs}) ->
 >     {MegaSecs*1000000+Secs, MicroSecs}.
 > 
 > timeval_to_now({Secs, MicroSecs}) ->
 >     {trunc(Secs / 1000000), Secs rem 1000000, MicroSecs}.

If you use {Secs div 1000000, ... } it'll make systems without
floating point happier.

Matthias



More information about the erlang-questions mailing list