« The Cook’s Thesaurus | Main | Zangband Tip: Digging Traps »

Unix Epoch Calculations

Coding bugs in Unix epoch time calculations may be avoided using the graphing method outlined here. Reasoning, however logical and detailed, does not work for me: I need to reference the visual diagram before trusting the resulting code. But first, a diversion down memory lane.

HISTORY
  A time() function appeared in Version 2 AT&T UNIX 
  and used to return time in sixtieths of a second in
  32 bits, which was to guarantee a crisis every 2.26
  years. Since the Version 6 AT&T UNIX time() scale
  was changed to seconds extending the pre-crisis
  stagnation period up to a total of 68 years.

Source: OpenBSD time(3) Documentation.

Technorati Tags:

  1. Graph Unix epoch time, and pick an arbitrary point to represent the current time when the date code encountered. Unix epoch time increases over time (discounting leap seconds and integer overflow problems), so use a linear 0 to ∞ line.

    Epoch-Graph-Base-1
  2. Divide the timeline into regions as appropriate for the coding problem. For example, data that expires—X.509 certificates or license codes—should be warned about if the expiration takes place soon, or critical warnings issued if already expired. This results in three regions:

    Epoch-Graph-Expiration-1
  3. In the code, create a variable for each time point, in this case expiration time and warn time. The Perl $EXPIRE_WARN_SECONDS variable (defined elsewhere) is added to the current time, as it lies to the right of the current time.

    my $current_time = time; my $time_expire = $current_time; my $time_warn = $current_time + $EXPIRE_WARN_SECONDS;

  4. Next, label an arbitrary time point in each region created by the previous step. In the case of X.509 certificate expiration monitoring, these would represent an expired certificate, a certificate in warning state, and a certificate requires no attention.

    Epoch-Graph-Labeled-2
  5. Finally, implement code to check the time derived from the X.509 certificate or license data. Reference the graph with each labeled point to determine the order of checks: expiration before warning, as an expired file is also less than the warn time. Match the > and < operators to the graph; larger numbers lie to the right. Use >= or <= if the time must coincide with the check, though for X.509 certificate expiration times, a second one way or the other should not matter, assuming the warning time allows for multiple checks before a certificate expires.

    # WRONG! Expired certificates are those # less than the expired time warn "expired" if $expire_date > $time_expire;

    # Accept epoch date of data to expire, return # whether expired, about to expire, or okay. sub expiration_check { my $expire_date = shift; my $current_time = time; my $time_expire = $current_time; my $time_warn = $current_time + $EXPIRE_WARN_SECONDS; if ( $expire_date <= $time_expire ) { return -1, 'error'; } elsif ( $expire_date <= $time_warn ) { return -1, 'warning'; } else { return 1, 'good'; } }

A tweak to make the above code more testable might be to pass in the current time, rather than generating it with each expiration_check call. Monitoring for certificate expiration with check-expire allows expiration monitoring, with configurable warning levels, and more.