Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

convert UTC time to system time zone's time with perl default method

by myuser (Initiate)
on Nov 24, 2010 at 13:28 UTC ( [id://873435]=perlquestion: print w/replies, xml ) Need Help??

myuser has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,

I would like to know how to convert the UTC time to systems time zone time. This perl script will be run in different systems which will have PST, AST or some other timezone.

Input is: 2010-09-06 15:06:53.512999 ( it is UTC time )
Output should be current systems time zone time.

Please let me know how to achive this through default functions / modules in perl. I cannot install any addon module as it is going to be used in many other systems.

I hope it is clear. I spent a lot of time in searching for how to do this, got lot of pages, but not got exact way to do this. Hope monks can help.
  • Comment on convert UTC time to system time zone's time with perl default method

Replies are listed 'Best First'.
Re: convert UTC time to system time zone's time with perl default method
by Corion (Patriarch) on Nov 24, 2010 at 13:31 UTC
Re: convert UTC time to system time zone's time with perl default method
by marto (Cardinal) on Nov 24, 2010 at 14:15 UTC

    "I cannot install any addon module as it is going to be used in many other systems."

    In addition to the advice you've already been given, you could use PAR or pp to package your script and modules it requires. See http://par.perl.org.

Re: convert UTC time to system time zone's time with perl default method
by Marshall (Canon) on Nov 27, 2010 at 07:07 UTC
    What you want to do is actually very straightforward.

    But, first let me congratulate you on using UTC as the "standard time" that your system operates in. This is the right way to go. Also, using a text based representation of this time for transfer between systems is better than using the epoch time since the representation of the epoch can vary from system to system.

    Epoch time (in seconds), like a GMT or UTC time is unambiguous, it is a steady onward marching time - there isn't any jump forward or backward stuff - well except for leap seconds). Exactly what date/time is considered to be "zero" - the beginning of time varies from system to system. Jan 1, 1970 is a common value. You convert the UTC time to this system specific number and then convert that number into the local time.

    Time::Local will already be on every system. The normal time functions would not have the precision implied by your time format. However, all you really need to do is figure out how the time zone change will affect the date and the hour - minutes,seconds and fraction of seconds will remain the same. So:
    -convert date/hour into the system's "epoch" time using timegm().
    -convert that epoch time into local time zone using localtime()
    code is shown below...

    I am in the PST time zone - this date/time was during PDST and the local time is -7 hours from UTC. If I change the month to 12 instead of 09- the time difference will be -8 hours and localtime() automatically adjusts for that. Note that both gmtime and localtime() handle leap years.

    Anyway, your code doesn't need to know what time zone this code is actually running in or whether it is DST or not - localtime() will take care of that.

    Note: I did have to consider some quirky historical stuff about the std I/F to the time functions - years are 1900 based and month numbering starts at zero instead of 1 because that makes it easier to use the month value as an index into some text describing the month. But this is easily handled once you know about it.

    Update:I didn't talk about going in the other direction (local->UTC) or doing "time math". There is some weirdness about that..for example when we leap backwards, at say 2AM, the time 1:15AM will occur twice on that local day although these two occurrences of 1:15AM represent 2 different UTC times. And you have to decide which of the 2 possible UTC times you mean (or accept default of the earliest one). Similarly, when we leap forward, one hour of local times "go missing" and the day only has 23 local hours. Important to note is that UTC time always has 24 hour days. And there is a direct mapping between the systems idea of "epoch time" and UTC. Do duration calculations using UTC. Anyway if your application is sensitive to these special 23 and 25 hour local days, you have some thinking to do - that's true whether you use some module or not.

    #!/usr/bin/perl -w use strict; use Time::Local; #needed for timegm() my $t = '2010-09-06 15:06:53.512999'; #( it is UTC time ) my $newstring = UTC2LocalString($t); print " UTC: $t\n"; print "Local: $newstring\n"; =PRINTS: UTC: 2010-09-06 15:06:53.512999 Local: 2010-09-06 08:06:53.512999 =cut sub UTC2LocalString { my $t = shift; my ($datehour, $rest) = split(/:/,$t,2); my ($year, $month, $day, $hour) = $datehour =~ /(\d+)-(\d\d)-(\d\d)\s+(\d\d)/; # proto: $time = timegm($sec,$min,$hour,$mday,$mon,$year); my $epoch = timegm (0,0,$hour,$day,$month-1,$year); # proto: ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = # localtime(time); my ($lyear,$lmonth,$lday,$lhour,$isdst) = (localtime($epoch))[5,4,3,2,-1]; $lyear += 1900; # year is 1900 based $lmonth++; # month number is zero based #print "isdst: $isdst\n"; #debug flag day-light-savings time return ( sprintf("%04d-%02d-%02d %02d:%s", $lyear,$lmonth,$lday,$lhour,$rest) ); }
      This is nice solution, except many timezones are new half hour, if even 15 minutes, so you should probably populate minutes as well, not just hours.
        Wow, I hadn't thought about this code for 7 years!

        Yes, there is some wild time weirdness out there and time zone offsets of 30 minutes for sure exist. If I remember right, there used to be a couple of places in the US that used a 30 minute offset for daylight savings time? I hadn't heard of a 15 minute time zone (or daylight time) difference before, but humans are capable of doing some amazingly stupid things! I guess that sort of confusion could be nice as an "excuse" if you are late to an appointment and the other side of the street is using local time 15 minutes ahead of you!

        If I were re-doing this, I would add the minutes and seconds into the code, leaving out only the fractions of seconds which cannot be represented by epoch time. Epoch is basically a 32 bit int representing number of seconds since an arbitrary date that is related to the release of Unix. So the fractions of a second cannot be represented.

        After 7 years, the algorithm remains sound: a) Convert the UTC date/time string into standard epoch seconds. Then, b) ask the local system what local time that epoch time means? I think the code is clear enough that I can leave that straight-forward extension to the reader...The epoch->local time standard function would handle this 30 minute stuff when given enough precision in the epoch time. So a 30 minute offset doesn't fundamentally change anything except the need for more precision.

        My advice to always log data in UTC remains. Local time is a presentation thing for management.

Re: convert UTC time to system time zone's time with perl default method
by fisher (Priest) on Nov 24, 2010 at 13:32 UTC
    May I ask you where you get your current input? May be you can grab time from other sources?
Re: convert UTC time to system time zone's time with perl default method
by ikegami (Patriarch) on Nov 24, 2010 at 16:29 UTC

    I cannot install any addon module as it is going to be used in many other systems.

    So if the code comes from PerlMonks.org, it's ok, but if the code comes from cpan.org, it's not???

      CPAN modules are sort of designed as black boxes. I don't feel that the implied suggestion to open up the black boxes is good advice. I feel instead we should help people learn to code from first principles if they want to.

      One world, one people

        No, you're suggesting we should help people learn the intricacies of time zones, not how to code. Most people can't even seem to remember days don't always have 24 hours.
Re: convert UTC time to system time zone's time with perl default method
by TomDLux (Vicar) on Nov 24, 2010 at 17:27 UTC

    What do you mean, "Input is ... "?

    Does the use type it into the command line when running the script? Is it scraped off a web site? Is it obtained using the gmtime() command? Does it come from Informix or KDB?

    As Occam said: Entia non sunt multiplicanda praeter necessitatem.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://873435]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2024-04-20 02:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found