CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Time Conversion Issue

 



TheBigAmbulance
Novice

Jul 13, 2012, 9:22 AM

Post #1 of 8 (6125 views)
Time Conversion Issue Can't Post

Greetings all,

I have a bit of a problem. I work for an ISP and have had to develop an 'newbie' perl script to parse copyright infringement letters sent to me in xml and msg. I have a good script, and it works well with the exception of time zones. In my larger script (attached to this post - too large to paste it all), I have the time stamp parsed out of either xml or mime into a variable called '$rawtime' that comes from $array[$i][1]. $rawtime data looks like this:


Code
2012-07-06T03:23:56.000Z 
2012-07-06T03:33:53.000Z
2012-07-06T03:36:48.000Z
2012-07-06T03:36:08.000Z
2012-07-06T03:35:25.000Z
2012-06-29T12:50:12-04:00
2012-06-29T11:20:53-04:00
2012-07-01T00:59:48-04:00
2012-07-01T00:59:44-04:00
2012-07-01T07:51:14-04:00
2012-07-01T10:00:31-04:00
2012-07-01T17:20:13-04:00
2012-07-01T21:19:26-04:00
2012-07-01T22:01:10-04:00
2012-07-02T13:21:11-04:00
2012-07-02T11:15:02-04:00
2012-07-02T18:10:37-04:00
2012-07-04T23:55:51-04:00
2012-07-04T22:19:59-04:00
2012-07-05T17:47:26-04:00
2012-07-06T08:35:53-04:00
2012-07-06T13:04:17-04:00
2012-07-06T17:56:16-04:00
2012-07-07T17:52:40-04:00
2012-07-09T07:46:29-04:00
2012-07-01T18:14:39Z
2012-07-09T11:06:50Z
2012-06-29T16:44:37Z
2012-07-02T19:20:29Z


As you can see, I am dealing with all sorts of variable times. Most are in Zulu time, but some of these 'yahoos' send their local time zone.

Here is the piece of my perl script that deals with the time:


Code
for (my $i = 0; $i < $arrayc; $i++) { 
my $rawtime = $array[$i][1];
print "Time - " . $rawtime . "\n";
my $dt = Date_ConvTZ($rawtime,'GMT','America/North_Dakota/Center');
my $year = substr($dt , 0 , 4);
my $month = substr($dt , 4 , 2);
my $date = substr($dt , 6 , 2);
my $hour = substr($dt , 8 , 2);
my $minute = substr($dt , 11 , 2);
my $sec = substr($dt , 14 , 2);
my $AMorPM;

if ($hour > 12) {
$hour = $hour - 12;
$AMorPM = "PM";
} elsif ($hour < 12) {
$AMorPM = "AM";
}

my $time = $year."-".$month."-".$date." ".$hour.":".$minute.":".$sec." ".$AMorPM;
$array[$i][1] = $time
}


So what I think I am going to have to do is have the script figure out which time zone the letter references, and then convert it to CST so it will match my logs.

Anyone have an opinion on what to do? Me not being a 100% perl programmer, I'm sure someone will be able to redo the portion above in like 4 lines! hehe

TIA!


(This post was edited by TheBigAmbulance on Jul 13, 2012, 9:50 AM)
Attachments: script.pl (5.99 KB)


FishMonger
Veteran / Moderator

Jul 13, 2012, 9:57 AM

Post #2 of 8 (6114 views)
Re: [TheBigAmbulance] Time Conversion Issue [In reply to] Can't Post

Do you plan on converting all timestamps to CST or just the ones that are not Zulu? Do you need/want to adjust for daylight savings, which would alter your offset between -5 and -6?

The sample that you posted has 2 different formats for indicating that it's Zulu. Do you have other formats for the timezone field that need to be considered?


(This post was edited by FishMonger on Jul 13, 2012, 10:00 AM)


TheBigAmbulance
Novice

Jul 13, 2012, 10:46 AM

Post #3 of 8 (6110 views)
Re: [FishMonger] Time Conversion Issue [In reply to] Can't Post

All values regardless of original time zone should be converted to the appropriate CST/CDT time dependent on CDT dates. I've thought about having the script pull the system time zone. That way, I wouldn't have to compensate for it within the conversion.

Unfortunately, I cannot control what they give me. There might be any number of variable way that they send the time.


FishMonger
Veteran / Moderator

Jul 13, 2012, 11:03 AM

Post #4 of 8 (6107 views)
Re: [TheBigAmbulance] Time Conversion Issue [In reply to] Can't Post

I don't have time right now to work up a tested solution, but I can point you in the right direction.

First, simply your parsing of the date. Instead of all of those substr statements, use a single unpack statement.

For example:

Code
my ($yr,$mo,$day,$hr,$min,$sec,$tz) = unpack("a4xa2xa2xa2xa2xa2a3", $date);


Then inspect the $tz value and based on it calculate the needed offset. If the value contains a 'z' then the offset will be -5. Otherwise adjust your default offset by the absolute value of $tz and use that to adjust the timestamp.

I'd probably use the Date::Calc module instead of Date::Manip because it has lower overhead.
http://search.cpan.org/~stbey/Date-Calc-6.3/lib/Date/Calc.pod


TheBigAmbulance
Novice

Jul 16, 2012, 7:58 AM

Post #5 of 8 (6086 views)
Re: [FishMonger] Time Conversion Issue [In reply to] Can't Post

Thanks for the info FishMonger...

I have rewritten a portion of my script to use the following:


Code
  my $systemTZ =  int(substr(strftime("%z", localtime()),0,3)); 
my $offendingTZ;

if ($TZ =~ m/(Z|z)/) {
$offendingTZ = 0;
} else {
$TZ =~ s/:00//g;
$offendingTZ = int($TZ);
}


This works to get the data as an interger I can work with. So now I have my system time zone ($systemTZ) and the offending info time stamp ($offendingTZ).

What I would like to do is configure a $deltaTZ so that I can rewrite the variable $hour by the difference.

For example... When $systemTZ is -5 and $offendingTZ is 0, I need to adjust the variable $hour -5 hours to convert ZULU time to the local time zone of the box. Likewise, if the $systemTZ is -5 and $offendingTZ is -4, I need to adjust the variable $hour -1 hour to convert EST to local time.

I am having a hard time trying to understand how an absolute value will help here, or did I go off on a tangent from what you suggested?

{EDIT} Actually, that won't work (modifying the variable $hour) because what happens when the time is around midnight, and the $date variable will need to change as well. Best bet is to take the variables ($offendingTZ and $systemTZ) and do a time zone conversion. However, I am having a hard time finding a script that doesn't use the actual names "I.E. CST".


(This post was edited by TheBigAmbulance on Jul 16, 2012, 8:52 AM)


FishMonger
Veteran / Moderator

Jul 16, 2012, 9:36 AM

Post #6 of 8 (6076 views)
Re: [TheBigAmbulance] Time Conversion Issue [In reply to] Can't Post

Did you check out the Date::Calc module? You'll want to look at the Delta_YMDHMS and Add_Delta_YMDHMS functions and possibly one or two others.

I'm tied up on other things right now, but will try to work up an example later today.


TheBigAmbulance
Novice

Jul 16, 2012, 2:15 PM

Post #7 of 8 (6065 views)
Re: [FishMonger] Time Conversion Issue [In reply to] Can't Post

No, I did not. But I think I came up with another answer.

Here is a different script trying to accomplish the same thing. I modified my $AMorPM portion of this script as well because it was not proper. It is working good! Wink


Code
#!/usr/bin/perl -w 
use strict;
use warnings;
use POSIX;

use Date::Manip;

my @array = (
"2012-07-06T03:23:56.000Z",
"2012-07-06T03:33:53.000Z",
"2012-07-06T03:36:48.000Z",
"2012-07-06T03:36:08.000Z",
"2012-07-06T03:35:25.000Z",
"2012-06-29T12:50:12-04:00",
"2012-06-29T11:20:53-04:00",
"2012-07-01T00:59:48-04:00",
"2012-07-01T00:59:44-04:00",
"2012-07-01T07:51:14-04:00",
"2012-07-01T10:00:31-04:00",
"2012-07-01T17:20:13-04:00",
"2012-07-01T21:19:26-04:00",
"2012-07-01T22:01:10-04:00",
"2012-07-02T13:21:11-04:00",
"2012-07-02T11:15:02-04:00",
"2012-07-02T18:10:37-04:00",
"2012-07-04T23:55:51-04:00",
"2012-07-04T22:19:59-04:00",
"2012-07-05T17:47:26-04:00",
"2012-07-06T08:35:53-04:00",
"2012-07-06T13:04:17-04:00",
"2012-07-06T17:56:16-04:00",
"2012-07-07T17:52:40-04:00",
"2012-07-09T07:46:29-04:00",
"2012-07-01T18:14:39Z",
"2012-07-09T11:06:50Z",
"2012-06-29T16:44:37Z",
"2012-07-02T19:20:29Z"
);

my $arrayc = @array;

my $rawtime;
my $offendingTZ;
my $rawdate;
my $TZ;
my $systemTZ = strftime("%z", localtime());


for (my $i = 0; $i < $arrayc; $i++) {
$rawtime = $array[$i];
$rawdate = substr($rawtime , 0 , 19);
$TZ = substr($rawtime , 19 );
if ($TZ =~ m/(Z|z)/) {
$offendingTZ = '0000';
} else {
$TZ =~ s/://g;
$offendingTZ = $TZ;
}
my $newdate = Date_ConvTZ($rawtime,$offendingTZ,$systemTZ);

my ($year,$month,$date,$hour,$minute,$sec) = unpack("a4a2a2a2xa2xa2", $newdate);

my $AMorPM;
if ($hour eq 00) {
$hour = 12;
$AMorPM = "AM";
} elsif ($hour eq 12) {
$hour = 12;
$AMorPM = "PM";
} elsif ($hour gt 12) {
$hour = $hour - 12;
$AMorPM = "PM";
} elsif ($hour lt 12) {
$AMorPM = "AM"
}

my $time = $year."-".$month."-".$date." ".$hour.":".$minute.":".$sec." ".$AMorPM;

print "Before - " . $rawdate . " After - " . $time . "\n";
}




Code
user@user-M6400:~/Documents/Copyright$ perl ./test2.pl 
Before - 2012-07-06T03:23:56 After - 2012-07-05 10:23:56 PM
Before - 2012-07-06T03:33:53 After - 2012-07-05 10:33:53 PM
Before - 2012-07-06T03:36:48 After - 2012-07-05 10:36:48 PM
Before - 2012-07-06T03:36:08 After - 2012-07-05 10:36:08 PM
Before - 2012-07-06T03:35:25 After - 2012-07-05 10:35:25 PM
Before - 2012-06-29T12:50:12 After - 2012-06-29 11:50:12 AM
Before - 2012-06-29T11:20:53 After - 2012-06-29 10:20:53 AM
Before - 2012-07-01T00:59:48 After - 2012-06-30 11:59:48 PM
Before - 2012-07-01T00:59:44 After - 2012-06-30 11:59:44 PM
Before - 2012-07-01T07:51:14 After - 2012-07-01 06:51:14 AM
Before - 2012-07-01T10:00:31 After - 2012-07-01 09:00:31 AM
Before - 2012-07-01T17:20:13 After - 2012-07-01 4:20:13 PM
Before - 2012-07-01T21:19:26 After - 2012-07-01 8:19:26 PM
Before - 2012-07-01T22:01:10 After - 2012-07-01 9:01:10 PM
Before - 2012-07-02T13:21:11 After - 2012-07-02 12:21:11 PM
Before - 2012-07-02T11:15:02 After - 2012-07-02 10:15:02 AM
Before - 2012-07-02T18:10:37 After - 2012-07-02 5:10:37 PM
Before - 2012-07-04T23:55:51 After - 2012-07-04 10:55:51 PM
Before - 2012-07-04T22:19:59 After - 2012-07-04 9:19:59 PM
Before - 2012-07-05T17:47:26 After - 2012-07-05 4:47:26 PM
Before - 2012-07-06T08:35:53 After - 2012-07-06 07:35:53 AM
Before - 2012-07-06T13:04:17 After - 2012-07-06 12:04:17 PM
Before - 2012-07-06T17:56:16 After - 2012-07-06 4:56:16 PM
Before - 2012-07-07T17:52:40 After - 2012-07-07 4:52:40 PM
Before - 2012-07-09T07:46:29 After - 2012-07-09 06:46:29 AM
Before - 2012-07-01T18:14:39 After - 2012-07-01 1:14:39 PM
Before - 2012-07-09T11:06:50 After - 2012-07-09 06:06:50 AM
Before - 2012-06-29T16:44:37 After - 2012-06-29 11:44:37 AM
Before - 2012-07-02T19:20:29 After - 2012-07-02 2:20:29 PM
user@user:~/Documents/Copyright$



This gives me the output (not parsed, but won't bore you with that) I desire. Probably not the cleanest/most effecient perl script around, but it gets the job done.

THANK YOU for all of your help!! It gave me a few ideas.


Chris Charley
User

Jul 20, 2012, 6:29 PM

Post #8 of 8 (5846 views)
Re: [TheBigAmbulance] Time Conversion Issue [In reply to] Can't Post

Maybe you could get an idea from this - it uses Date::Parse for the various times and their timezones. (My localtime zone is EDT, New York).

Code
 #!/usr/bin/perl 
use strict;
use warnings;
use POSIX qw/ strftime /;
use Date::Parse qw/ str2time /;

my @array = (
"2012-07-06T03:23:56.000Z",
"2012-07-06T03:33:53.000Z",
"2012-07-06T03:36:48.000Z",
"2012-07-06T03:36:08.000Z",
"2012-07-06T03:35:25.000Z",
"2012-06-29T12:50:12-04:00",
"2012-06-29T11:20:53-04:00",
"2012-07-01T00:59:48-04:00",
"2012-07-01T00:59:44-04:00",
"2012-07-01T07:51:14-04:00",
"2012-07-01T10:00:31-04:00",
"2012-07-01T17:20:13-04:00",
"2012-07-01T21:19:26-04:00",
"2012-07-01T22:01:10-04:00",
"2012-07-02T13:21:11-04:00",
"2012-07-02T11:15:02-04:00",
"2012-07-02T18:10:37-04:00",
"2012-07-04T23:55:51-04:00",
"2012-07-04T22:19:59-04:00",
"2012-07-05T17:47:26-04:00",
"2012-07-06T08:35:53-04:00",
"2012-07-06T13:04:17-04:00",
"2012-07-06T17:56:16-04:00",
"2012-07-07T17:52:40-04:00",
"2012-07-09T07:46:29-04:00",
"2012-07-01T18:14:39Z",
"2012-07-09T11:06:50Z",
"2012-06-29T16:44:37Z",
"2012-07-02T19:20:29Z"
);

for my $dt (@array) { # for my $datetime
printf "RAW - %s\tLocal - %s\n",
substr($dt, 0, 19),
strftime("%Y-%m-%d %I:%M:%S %p", localtime(str2time($dt)));
}

__END__
C:\Old_Data\perlp>perl t3.pl
RAW - 2012-07-06T03:23:56 Local - 2012-07-05 11:23:56 PM
RAW - 2012-07-06T03:33:53 Local - 2012-07-05 11:33:53 PM
RAW - 2012-07-06T03:36:48 Local - 2012-07-05 11:36:48 PM
RAW - 2012-07-06T03:36:08 Local - 2012-07-05 11:36:08 PM
RAW - 2012-07-06T03:35:25 Local - 2012-07-05 11:35:25 PM
RAW - 2012-06-29T12:50:12 Local - 2012-06-29 12:50:12 PM
RAW - 2012-06-29T11:20:53 Local - 2012-06-29 11:20:53 AM
RAW - 2012-07-01T00:59:48 Local - 2012-07-01 12:59:48 AM
RAW - 2012-07-01T00:59:44 Local - 2012-07-01 12:59:44 AM
RAW - 2012-07-01T07:51:14 Local - 2012-07-01 07:51:14 AM
RAW - 2012-07-01T10:00:31 Local - 2012-07-01 10:00:31 AM
RAW - 2012-07-01T17:20:13 Local - 2012-07-01 05:20:13 PM
RAW - 2012-07-01T21:19:26 Local - 2012-07-01 09:19:26 PM
RAW - 2012-07-01T22:01:10 Local - 2012-07-01 10:01:10 PM
RAW - 2012-07-02T13:21:11 Local - 2012-07-02 01:21:11 PM
RAW - 2012-07-02T11:15:02 Local - 2012-07-02 11:15:02 AM
RAW - 2012-07-02T18:10:37 Local - 2012-07-02 06:10:37 PM
RAW - 2012-07-04T23:55:51 Local - 2012-07-04 11:55:51 PM
RAW - 2012-07-04T22:19:59 Local - 2012-07-04 10:19:59 PM
RAW - 2012-07-05T17:47:26 Local - 2012-07-05 05:47:26 PM
RAW - 2012-07-06T08:35:53 Local - 2012-07-06 08:35:53 AM
RAW - 2012-07-06T13:04:17 Local - 2012-07-06 01:04:17 PM
RAW - 2012-07-06T17:56:16 Local - 2012-07-06 05:56:16 PM
RAW - 2012-07-07T17:52:40 Local - 2012-07-07 05:52:40 PM
RAW - 2012-07-09T07:46:29 Local - 2012-07-09 07:46:29 AM
RAW - 2012-07-01T18:14:39 Local - 2012-07-01 02:14:39 PM
RAW - 2012-07-09T11:06:50 Local - 2012-07-09 07:06:50 AM
RAW - 2012-06-29T16:44:37 Local - 2012-06-29 12:44:37 PM
RAW - 2012-07-02T19:20:29 Local - 2012-07-02 03:20:29 PM



(This post was edited by Chris Charley on Jul 20, 2012, 9:02 PM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives