in reply to high speed/efficiency http date to unix time, leap years handling?
So it appears that we have a simplicity vs performance thing going on. Using a regex to get the values is expensive versus even complex substr code.
If the speed is really that important, then I think we are into using some kind of C code, perhaps inline C. I haven't done that before (never was necessary before with Perl), but I'm sure that I could write some real fast C code.
Albeit easier to understand, this code is slower than the more complex versions.... most of the time difference is spent in the regex, which is actually not that surprising.
Original post continues....sub another_converter { my $httpdate = shift; my ($mday,$mon,$year,$hours,$min,$sec) = $httpdate =~ m/(\d+)\s+(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)/; my $month_num = $month2num{$mon}; my $thistime = timegm($sec,$min,$hours,$mday,$month_num,$year); return ($thistime); }
Giving timegm() a 4 digit year is completely fine - no need anymore to fiddle with this 1900 adjustment anymore to get a 2 digit year. A date before 1970 will result in a negative epoch time. The one "gottcha" is that the month is zero based instead of one based (0..11), but the hash table takes care of that. timegm() will handle the leap years for you.
Update:#!/usr/bin/perl -w use strict; use Time::Local; # the prototype for timegm().... # my $time = timegm($sec,$min,$hours,$mday,$mon,$year); # mday is 1...31 max -> day in month one based # mon is 0..11 -> month in year zero based !!!!!Wow!!! my %month2num = ( 'Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 'May' => 4, 'Jun' => 5, 'Jul' => 6, 'Aug' => 7, 'Sep' => 8, 'Oct' => 9, 'Nov' => 10, 'Dec' => 11, ); my $httpdate = 'Wed, 25 Aug 2010 09:56:38 GMT'; print "httpdate = $httpdate\n"; my ($mday,$mon,$year,$hours,$min,$sec) = $httpdate =~ m/(\d+)\s+(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)/; $mon = $month2num{$mon}; print "mday=$mday mon=$mon year=$year hours=$hours min=$min sec=$sec\n +"; #prints: mday=25 mon=7 year=2010 hours=09 min=56 sec=38 my $thistime = timegm($sec,$min,$hours,$mday,$mon,$year); print "unix time = $thistime\n"; print "\nusing gmtime() to make sure that we can convert back!\n"; print scalar (gmtime ($thistime)),"\n"; print "another way to use gmtime()\n"; print "".gmtime ($thistime),"\n"; #another way to force scalar con +text __END__ PRINTS: httpdate = Wed, 25 Aug 2010 09:56:38 GMT mday=25 mon=7 year=2010 hours=09 min=56 sec=38 unix time = 1282730198 using gmtime() to make sure that we can convert back! Wed Aug 25 09:56:38 2010 another say to use gmtime() Wed Aug 25 09:56:38 2010
Found this text from a previous post lounging around in my temp directory. But I think it is on topic with the 5 main time functions. There are many modules and many functions, but understanding these will take one a long way.
There are three time functions included within Perl itself:
1. localtime()
2. gmtime()-this returns the value of the time function
in 9 parts from an "epoch GMT basedtime"
3. time() - makes an epoch second value for "now", can be used by either gmtime() or localtime()
The module Time::Local contains the inverse of those functions:
1. timelocal()
2. timegm() - this takes the 9 parts and generates the epoch time.
3. (there is no "inverse" of time() per sea)
The operating system keeps track of "time" based upon a continually incrementing integer number of seconds since a specific start date/time. This is called the "epoch time" (returned time() value of zero). For Unix and Windows this is 00:00:00 Jan 1, 1970. I seem to remember that some versions of Apple's OS'es use a different value for this "epoch date/time". The point being is that this "epoch time" value is not transportable in a general sense between platforms. Converting an "epoch time" to a text string is a good way to ensure portability.
The time() function produces the current value of this continuously incrementing number of "epoch seconds" since the start of the "epoch" and corresponds to "now". This number never decreases and is independent of daylight savings time. When we "set our clocks back one hour", this "seconds since epoch" number just keeps growing. Just because we set our clocks back one hour, that doesn't change the fact that more seconds are continuing to accrue since the "epoch time".
The general way to do "time math" is to convert to epoch seconds, do math in seconds and then convert back to a string. The DateTime module does it that way too and it can apply some fancy "correction values for leap seconds, etc.
|
|---|