update: timezone offset calc and date formatting

Discussion in 'Perl Misc' started by Leendert Bottelberghs, Apr 8, 2005.

  1. Hi all,

    a few days ago I posted on this list about timezone offset calculations.
    After some suggestions, I both tested with the use of some Date modules,
    as rewrote my own routine for calcutating the time offset and formatting a
    date-time string. Benchmark tests show that my own routine is about 8000%
    (!!!) faster than using the Date::Manip module. This is especially
    interesting when you have to format dates at a high rate, such as for
    http-logging. I'll elaborate some more on my findings in this post.

    I need a formatted date-time string for a mod_perl module that writes
    access logs. Apache uses it's own date format, which includes the timezone
    offset. As a log entry is written for every request, and thus the date
    format has to be calculated for every request, I want it's overhead to be

    I wanted to test two different modules for date formatting and calcs. I
    tried to install the - very complete - module DateTime. But for some
    reasons it wouldn't install on my system. Besides the fact that it is very
    complete, it also seemed like to be a bit over-the-top for what I needed.
    I succeeded in using Date::Manip for constructing the date-format string,
    which looks like: [08/Apr/2005:11:24:03 +0100]. The code for constructing
    this string is fairly simple and concise:

    sub DateManip {
    my $time = &UnixDate("today", "[%d/%b/%Y:%H:%M:%S %z]"); return $time;

    Where as my own routine is a bit more complex:

    sub homeBrew {
    my @lctime = localtime();
    my @gmtime = gmtime();
    my $mo = (($lctime[2]-$gmtime[2])%24)*60+($lctime[1]-$gmtime[1])%60;
    my $tz = int($mo/60)*100+($mo/abs($mo))*($mo%60);
    my $time = sprintf "[%02d/%3s/%4d:%02d:%02d:%02d %+05d]",
    (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)[$lctime[4]]),
    return $time;

    The main calculations are for the timezone difference. I used Benchmark to
    measure the performace of both routines, and here are the results (P4

    Benchmark: running DateManip, homeBrew for at least 10 CPU seconds...
    DateManip: 10 wallclock secs (10.46 usr + 0.02 sys = 10.48 CPU) @
    280.34/s (n=2938)
    homeBrew: 11 wallclock secs ( 9.74 usr + 0.32 sys = 10.06 CPU) @
    22500.00/s (n=226350)

    Rate DateManip homeBrew
    DateManip 280/s -- -99% homeBrew 22500/s 7926%

    I'd say that is quite a difference! Since I want to use this on a
    webserver, where a probable 100-300 requests/second arrive, I don't want
    my CPU to be fully occupied formatting a date.

    The main performance gain is in the algorithm for calculating the timezone
    offset. In the previous discussion, "Geoff" pointed out, that timezone
    offset is not always in full hours, but can also differ 30 minutes. He
    suggested calculating the difference in seconds. So I did, using
    Time::Local to convert localtime() and gmtime() to seconds. After
    calculating the difference in seconds, I have to convert it back to hours
    and minutes in order to get the proper format. This converting was
    obviously CPU-consuming, as this routine was approx. 15x slower than the
    algorithm used in the current routine. This algorithm works as follows: 1.
    calculate hour difference:
    a = (localtime(hours) - gmtime(hours))%24
    2. convert these hours to minutes:
    b = a*60
    3. calculate the minute difference:
    c = (localtime(minutes) - gmtime(minutes))%60
    4. sum to get the total time diff in minutes:
    d = b + c
    5. prepare to format to 4 digit hhmm number:
    e = int(d/60)*100+(d/abs(d))*(d%60)

    To demonstrate the efficiency of using this algorithm in stead of the
    Date::Manip method, I did another test where I only formatted the
    time-zone offset. The routines:

    sub homeBrew {
    my @lctime = localtime();
    my @gmtime = gmtime();
    my $mo = (($lctime[2]-$gmtime[2])%24)*60+($lctime[1]-$gmtime[1])%60;
    my $tz = int($mo/60)*100+($mo/abs($mo))*($mo%60);
    my $time = sprintf "%+05d", $tz;
    return $time;
    sub DateManip {
    my $time = &UnixDate("today", "%z");
    return $time;

    The Benchmark results:

    Benchmark: running DateManip, homeBrew for at least 10 CPU seconds...
    DateManip: 11 wallclock secs (10.51 usr + 0.02 sys = 10.53 CPU) @
    256.13/s (n=2697)
    homeBrew: 11 wallclock secs ( 9.85 usr + 0.38 sys = 10.23 CPU) @
    28406.06/s (n=290594)

    Rate DateManip homeBrew
    DateManip 256/s -- -99% homeBrew 28406/s 10991%

    This shows that my algorithm is about 100x faster than using Date::Manip.
    A significant difference I'd say.

    Conclusion: if you have to format time in a high load environment, it's
    definitely worth it to programm your own algorithms for formatting date
    and time. If anyone has an even more efficient algorithm than mine, I'd
    like to hear it.

    -leendert bottelberghs
    Leendert Bottelberghs, Apr 8, 2005
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?Sm9ubnk=?=

    Timezone offset for a future date.

    =?Utf-8?B?Sm9ubnk=?=, Oct 18, 2007, in forum: ASP .Net
    Oct 23, 2007
  2. Kaye Ng

    ruby calc.rb or just calc.rb

    Kaye Ng, Jul 26, 2010, in forum: Ruby
    Kaye Ng
    Jul 28, 2010
  3. Leendert Bottelberghs

    time zone offset calc with localtime and gmtime

    Leendert Bottelberghs, Apr 4, 2005, in forum: Perl Misc
    Apr 5, 2005
  4. Bob
    Paul Lalli
    Sep 1, 2005
  5. Roy Smith
    Roy Smith
    Jan 27, 2013

Share This Page