PDA

View Full Version : some help needed..changing of time format from 12hour format to 24hour format


ivernrawks
03-23-2006, 04:32 AM
i wana know how to change time format from 12hr format to 24 hr format..

i browsed thru many websites and cannot find the answer to it..

played around with the codes and cant get the output right..

help !

FishMonger
03-23-2006, 05:04 AM
We need more details.

Are you trying to change the format of the system date?

Are you trying to change the display of a date string in your scripts output.

Is the date based on the current date/time or is it some other date string that you need to reformat?

Can you post your code?

ivernrawks
03-23-2006, 05:08 AM
$clock_type = 2;
if($clock_type eq 1) {
@hours = ('12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11',
'12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11',);
}
else {
@hours = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11',
'12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23',);
}

print "$time<br>\n";

#this is only one of the codes i have been trying on..

I have a file which is updated to my web server at periodic intervals with updated records. The time displayed is in 12hr format. I wanna change to 24 hour format (eg. 02:30:00pm = 14:30:00hrs).

FishMonger
03-23-2006, 05:35 AM
Your code is even more vauge than your description. Can you post a few lines from your log file and a more complete sample of your code.

There are a number of date/time format modules that you may want to look at.

http://search.cpan.org/~sbeck/DateManip-5.44/Manip.pod
http://search.cpan.org/~roode/Time-Format-1.02/Format.pm
http://search.cpan.org/~stbey/Date-Calc-5.4/Calc.pod

ivernrawks
03-23-2006, 05:48 AM
use CGI;
$q = new CGI;

print $q->header;
($sortseq, $togglesort) = split (/&/,$ENV{'QUERY_STRING'});

use Time::Local;

$Tdate = timelocal((localtime)[0,1,2,3,4,5]); #today's date
my($seconds,$minutes,$hours,$day_of_month,$month,$year,$wday,$yday,$isdst)=localtime($Tdate);

$eday = sprintf("%02d", $day_of_month);
$emth = sprintf("%02d", $month+1);
$eyr = sprintf("%04d", $year+1900);

$rev_date = "$eyr"."$emth"."$eday";

$MAIN_PATH = "c:/Web/ivern/Visualize/"; # PATH
$date_file = "50SG_"."$rev_date".".txt"; # eg. 50SG_20060202

$logfile = "$MAIN_PATH"."$date_file";

open(INF,"$logfile") or dienice(print "can't open $logfile: $!");

@ary = <INF>;
close (INF);

foreach $i (@ary) {
chomp($i);
($cs,$flocation,$nn,$tc,$eqid,$date,$time,$rid,$rtc,$rn,$cn,$tid,$taid,$urgency) =
split(/;/,$i);
push@NN,$nn; # Request Number
}

# For a 12 hour clock use 1 for a 24 hour clock use 2.
$clock_type = 2;
if($clock_type eq 1) {
@hours = ('12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11',
'12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11',);
}
else {
@hours = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11',
'12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23',);
}

Part of the code looks like this..I'm reading the timings in a file that has been created..
The time of each line is still in 12hour format..I still cannot change it to 24hour format..

FishMonger
03-23-2006, 06:37 AM
There are a couple approachs that can be taken, either with or without the modules I pointed to. However, without seeing the actual date string from the log file, I can only make guesses as to the proper choice and the guess I make probably won't match your date format, so it would be useless to you.

FishMonger
03-23-2006, 07:20 AM
Here's a cleaned up version of the first part of your script. For the date/time formating I'm inclined to use the Data::Manip module, but I'll wait to post some examples until you can provide the sample of the actual date and time format that's in your log file. A couple sample lines of the log file would be best.

use POSIX;
use CGI;
$q = new CGI;

print $q->header;

# this is questionable, but I left it alone...why aren't you using the cgi module for this part?
($sortseq, $togglesort) = split (/&/,$ENV{'QUERY_STRING'});

$rev_date = strftime("%Y%m%d", localtime);

$MAIN_PATH = "c:/Web/ivern/Visualize/"; # PATH
$date_file = "50SG_$rev_date.txt"; # eg. 50SG_20060202

$logfile = "$MAIN_PATH$date_file";

FishMonger
03-23-2006, 07:40 AM
Actually, instead of the module, we can use a regex. Assuming your $time var holds a time format such as:

$time = '02:30:34pm';

This regex will reformat it to 24 hr display
$time =~ s/^(\d\d)(:\d\d:\d\d)pm/($1+12)."$2hrs"/e;

$time now holds:
14:30:34hrs

ivernrawks
03-23-2006, 07:48 AM
Sample of the information in the text file as below:

Open;Nanyang Poly (527/CHYP);2565389;Opened;SW;20060224;09:01:01AM;100000756;RS_GROUP;SG FS SGP;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:05AM;100000756;RS_GROUP;SG FS SGP;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:21AM;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:21AM;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;Assigned;SW;20060224;09:01:26AM;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium
Open;Toa Payoh (385/CHTP);2565401;Opened;SW;20060224;09:40:48AM;100000756;RS_GROUP;SG FS SGP;;3738171;4992494;Medium
FW;Toa Payoh (385/CHTP);2565401;In Planning;SW;20060224;09:40:55AM;100000756;RS_GROUP;SG FS SGP;;3738171;4992494;Medium

FishMonger
03-23-2006, 08:01 AM
Good, now it's more clear and we can easily use the regex instead of the module.

The regex needs a minor change. We need to either add the i modifier at the end to make it case insensitive, or if you know that the AM/PM will always be in upper case, just change it to upercase in the regex.

$time =~ s/^(\d\d)(:\d\d:\d\d)pm$/($1+12)."$2hrs"/ei;
$time =~ s/^(\d\d)(:\d\d:\d\d)PM$/($1+12)."$2hrs"/e;

Either one of those will work, but it needs to be applied in the foreach loop, something like this:

foreach $i (@ary) {
($cs,$flocation,$nn,$tc,$eqid,$date,$time,$rid,$rtc,$rn,$cn,$tid,$taid,$urgency) = split(/;/,$i);
push@NN,$nn; # Request Number

$time =~ s/^(\d\d)(:\d\d:\d\d)PM$/($1+12)."$2hrs"/e;
print join ';', ($cs,$flocation,$nn,$tc,$eqid,$date,$time,$rid,$rtc,$rn,$cn,$tid,$taid,$urgency);
}


EDIT:
Oops, I only reformated the PM times. This will do both.

unless($time =~ s/AM$/hrs/) {
$time =~ s/^(\d\d)(:\d\d:\d\d)PM$/($1+12)."$2hrs"/e;
}

ivernrawks
03-23-2006, 08:17 AM
i just started on perl. i tried for a week or more and you finished it in awhile. it should be working with the code! OH MY GOD. YOURE THE MAN!

DAMN........ YOU TOTALLY ROCK MY WORLD.......

THANKS!!!!!!!!!! sorry. too excited.

:D

FishMonger
03-23-2006, 08:25 AM
Glad I was able to help. I should have seen what you needed 2 hours ago, but I was thrown off a little with your use of the arrays.

ivernrawks
03-23-2006, 08:45 AM
Sorry dude.
I just started perl a week plus only.
Will improve on my perl.
:D

ivernrawks
03-24-2006, 02:54 AM
There's a slight problem.

For 12:48:00 PM, it is converted to 24:48:00 hrs.

By right it should be converted to 00:48:00 hrs.

How you go about doing it?

FishMonger
03-24-2006, 04:08 AM
Shouldn't it remain 12:48:00? 00:48:00 is 48 minutes after midnight.

There may be a couple other issues like this, but see if this adjustment satisfies your requirement.

unless($time =~ s/AM$/hrs/) {
$time =~ s/^(\d\d)(:\d\d:\d\d)PM$/($1+12)."$2hrs"/e;
$time =~ s/^12/00/;
$time =~ s/^24/12/;
}

ivernrawks
03-27-2006, 02:18 AM
It doesn't work
But thanks anyway!
I think by using the codes below it will work better.

unless($time =~ s/AM$/hrs/) {
$time =~ s/^(\d\d)(:\d\d:\d\d)PM$/($1+12)."$2hrs"/e;
}

($hr, $min, $sec) = split(/:/, $time);

if ($hr eq "24") {
$hr = "00";
}

$time = "$hr:$min:$sec";

KevinADC
03-27-2006, 07:49 AM
there never should be an hour displayed as 24:00:00. Once the time is 23:59:59 the next second the time is displayed as 00:00:00. So checking to see if the hour equals 24 will never return true.

KevinADC
03-27-2006, 08:12 AM
Here is a suggestion:

$time =~ s/(\d\d)(:\d\d:\d\d)(\w\w)/military($1,$2,$3)/e;
print $time;

sub military {
my($hr,$ms,$pm) = @_;
$hr+=12 if ($pm eq 'PM' and $hr < 12);
$hr='00' if ($pm eq 'AM' and $hr == 12);
return("$hr$ms".'hrs');
}

ivernrawks
03-29-2006, 02:56 AM
Hey Kevin..

Thanks!

I think you have solved my problem.

12 PM = 12 hrs?

12 AM = 0 hrs?

ivernrawks
03-29-2006, 03:11 AM
Actually my codes below work too right??

unless($time =~ s/AM$/hrs/) {
$time =~ s/^(\d\d)(:\d\d:\d\d)PM$/($1+12)."$2hrs"/e;
}

($hr, $min, $sec) = split(/:/, $time);

if ($hr eq "24") {
$hr = "12";
}

$time = "$hr:$min:$sec";

KevinADC
03-29-2006, 06:37 AM
Only being able to see the snippet you posted I would think it will not work in all situations.

You really spread this question around, I have seen it on at least three forums.

KevinADC
03-29-2006, 07:00 AM
OK, I did a comparison with the snippet you posted and the one I posted:

print "Ivern \tKevin\n";
print "---------------------------\n";

while(<DATA>){
chomp;
my ($time1,$time2) = ($_,$_);
unless($time1 =~ s/AM$/hrs/) {
$time1 =~ s/^(\d\d)(:\d\d:\d\d)PM$/($1+12)."$2hrs"/e;
}
my ($hr, $min, $sec) = split(/:/, $time1);
$hr = 12 if ($hr eq "24");
$time1 = "$hr:$min:$sec";
print "$time1\t";
$time2 =~ s/(\d\d)(:\d\d:\d\d)(\w\w)/military($1,$2,$3)/e;
print "$time2\n";
}

sub military {
my($hr,$ms,$pm) = @_;
$hr+=12 if ($pm eq 'PM' and $hr < 12);
$hr='00' if ($pm eq 'AM' and $hr == 12);
return("$hr$ms".'hrs');
}
__DATA__
00:00:00AM
12:30:30AM
12:59:59AM
09:01:01AM
11:59:59AM
12:00:00PM
12:59:59PM
01:30:00PM
10:30:00PM
11:59:59PM

results:

Ivern Kevin
---------------------------
00:00:00hrs 00:00:00hrs
12:30:30hrs 00:30:30hrs
12:59:59hrs 00:59:59hrs
09:01:01hrs 09:01:01hrs
11:59:59hrs 11:59:59hrs
12:00:00hrs 12:00:00hrs
12:59:59hrs 12:59:59hrs
13:30:00hrs 13:30:00hrs
22:30:00hrs 22:30:00hrs
23:59:59hrs 23:59:59hrs


Notice the first 2nd and 3rd times are not converted correctly by your code. They are not in proper military time format. But if that's how you want the results to be then your code is good.

FishMonger
03-29-2006, 07:08 AM
Is there some reason why the solution I gave works for me but fails for you? Are you appling it to a different set of data than what you've posted?

Here's my test script and its output that changes the 12hr format to 24hr.

#!/usr/bin/perl

use strict;

while(<DATA>) {
print;
chomp;
my ($cs,$flocation,$nn,$tc,$eqid,$date,$time,$rid,$rtc,$rn,$cn,$tid,$taid,$urgency) = split /;/;
unless($time =~ s/AM$/hrs/) {
$time =~ s/^(\d\d)(:\d\d:\d\d)PM$/($1+12)."$2hrs"/ie;
$time =~ s/^24/12/; # checking for 24 is needed since we added 12 to all PM times.
}
print join ';', ($cs,$flocation,$nn,$tc,$eqid,$date,$time,$rid,$rtc,$rn,$cn,$tid,$taid,$urgency), "\n\n";
}

__DATA__
Open;Nanyang Poly (527/CHYP);2565389;Opened;SW;20060224;00:01:01AM;100000756;RS_GROUP;SG FS SGP;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:05AM;100000756;RS_GROUP;SG FS SGP;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:21AM;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:21AM;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;Assigned;SW;20060224;09:01:26AM;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium
Open;Toa Payoh (385/CHTP);2565401;Opened;SW;20060224;12:40:48PM;100000756;RS_GROUP;SG FS SGP;;3738171;4992494;Medium
FW;Toa Payoh (385/CHTP);2565401;In Planning;SW;20060224;12:45:55PM;100000756;RS_GROUP;SG FS SGP;;3738171;4992494;Medium

Outputs:
Open;Nanyang Poly (527/CHYP);2565389;Opened;SW;20060224;00:01:01AM;100000756;RS_GROUP;SG FS SGP;;3738166;4992484;Medium
Open;Nanyang Poly (527/CHYP);2565389;Opened;SW;20060224;00:01:01hrs;100000756;RS_GROUP;SG FS SGP;;3738166;4992484;Medium;

FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:05AM;100000756;RS_GROUP;SG FS SGP;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:05hrs;100000756;RS_GROUP;SG FS SGP;;3738166;4992484;Medium;

FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:21AM;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:21hrs;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium;

FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:21AM;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;In Planning;SW;20060224;09:01:21hrs;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium;

FW;Nanyang Poly (527/CHYP);2565389;Assigned;SW;20060224;09:01:26AM;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium
FW;Nanyang Poly (527/CHYP);2565389;Assigned;SW;20060224;09:01:26hrs;100002324;RS_EMPLOYEE;Batalon, Mr. Michael;;3738166;4992484;Medium;

Open;Toa Payoh (385/CHTP);2565401;Opened;SW;20060224;12:40:48PM;100000756;RS_GROUP;SG FS SGP;;3738171;4992494;Medium
Open;Toa Payoh (385/CHTP);2565401;Opened;SW;20060224;12:40:48hrs;100000756;RS_GROUP;SG FS SGP;;3738171;4992494;Medium;

FW;Toa Payoh (385/CHTP);2565401;In Planning;SW;20060224;12:45:55PM;100000756;RS_GROUP;SG FS SGP;;3738171;4992494;Medium
FW;Toa Payoh (385/CHTP);2565401;In Planning;SW;20060224;12:45:55hrs;100000756;RS_GROUP;SG FS SGP;;3738171;4992494;Medium;

KevinADC
03-29-2006, 07:16 AM
Your code works FishMonger for all times except 12:00:00AM thru 12:59:59AM which doesn't get converted to 00:00:00hrs thru 00:59:59hrs.

FishMonger
03-29-2006, 07:18 AM
Oops, I forgot to deal with correcting the 12:00:01am to 12:59:59am times

if($time =~ s/AM$/hrs/) {
$time =~ s/^12/00/;
} else {
$time =~ s/^(\d\d)(:\d\d:\d\d)PM$/($1+12)."$2hrs"/ie;
$time =~ s/^24/12/;
}

Edit: If you like, we can shorten the syntax a little
$time =~ s/^12/00/ if $time =~ s/AM$/hrs/;
$time =~ s/^24/12/ if $time =~ s/^(\d\d)(:\d\d:\d\d)PM$/($1+12)."$2hrs"/e;

ivernrawks
03-29-2006, 08:58 AM
Okay. Thanks KevinADC and FishMonger.

Just curious.

Sorry I'm very foreign to Perl language.

There are many ways to write a script?

Cause like both of your writing styles are different.

The one that is easier to understand or the least lines?

I reckon both can be used but which one to use?

FishMonger
03-29-2006, 09:14 AM
Which one to use is a personal choice mainly based on which one you find easier to understand. They are fairly close in efficiency. I ran a couple benchmark tests against the small sample data using both the Benchmark module and the Time::HiRes module and my code was about 10% faster.

FishMonger
03-29-2006, 10:48 AM
Here's an easier option that uses the Time::Format module.

use Time::Format '%manip';
$ENV{'TZ'} = 'PST'; # depending on the system you're on, this line may not be needed

while (<DATA>) {
print;
chomp;
my ($cs,$flocation,$nn,$tc,$eqid,$date,$time,$rid,$rtc,$rn,$cn,$tid,$taid,$urgency) = split /;/;
$time = $manip{"%H:%M:%Shrs", $time};
print join ';', ($cs,$flocation,$nn,$tc,$eqid,$date,$time,$rid,$rtc,$rn,$cn,$tid,$taid,$urgency), "\n\n";
}

KevinADC
03-29-2006, 10:23 PM
Which one to use is a personal choice mainly based on which one you find easier to understand. They are fairly close in efficiency. I ran a couple benchmark tests against the small sample data using both the Benchmark module and the Time::HiRes module and my code was about 10% faster.

Yes, I agree with FishMonger, personal preference and how you learned perl in the first place (and how much you know) dictates how you write code. If you really need to go for maximum efficiency then you have to try different things and test the code to see what works best in any given situation. Ten different people could write ten different ways of doing what you are trying to do, it's part of perls TIMTOWTDI** maxim, but some people find that flexibility in perl to be confusing too.



** There Is More Than One Way To Do It

ivernrawks
03-30-2006, 07:34 AM
Okay.

Thanks guys.

Really appreciate what you all have done.

:)

ivernrawks
04-04-2006, 07:35 AM
I tried to sort the times by asc and desc order. However it does not work.
Why is it so? Is my code wrong?

sub bynn {

if ($sortseq == "") { $sortseq = "2";}

@a = split(/;/,$a);
@b = split(/;/,$b);
if ($togglesort eq "" or $togglesort eq "b") {&desc;} else {&asc;}

} # End Subroutine

sub asc { $a[$sortseq] cmp $b[$sortseq];}
sub desc { $b[$sortseq] cmp $a[$sortseq];}

KevinADC
04-04-2006, 08:44 AM
you need to show what it is you are sorting. Are you sorting the time after converting it to military time format?

ivernrawks
04-04-2006, 09:10 AM
For example,
00:00:00hrs
09:01:01hrs
12:59:59hrs
00:30:30hrs
12:30:30hrs
Button

Like I click a button and it rearranges in desc order. When I click it again, it rearranges in asc order.

Cause I tried using my codes. It jumbled up all the times. Only some times are in asc/desc order, below them are mixed times.

I wanna sort it like for example;
in asc order,
00:00:00hrs
00:30:30hrs
09:01:01hrs
12:30:30hrs
12:59:59hrs

KevinADC
04-04-2006, 08:04 PM
you have to first compare the hour, then the minute, then the seconds and use the <=> operator instead of the "cmp" operator to correctly sort digits. Or you could convert the times into total amount of seconds and just compare the amount of seconds, or there is probably a date module that will do it all for you.

ivernrawks
04-05-2006, 04:32 AM
Sorry. Do not get what you mean and i do not know how to write this. Any easier method? Use a if else loop ?

ivernrawks
04-05-2006, 04:38 AM
Is it something like,
#!/usr/bin/perl
print "Content-type:text/html\n\n";

open(INF,"data.db") or dienice("Can't open data.db: $1 \n");

@kites = <INF>;
close(INF);

print "<h3>Kites, by price:</h3>\n\n";
foreach $i (sort byprice @kites) {
chomp($i);
($stocknum,$name,$status,$price) = split(/\|/, $i);
print "$name (#$stocknum) - \$$price<br>\n";
}

sub byprice {
@a = split(/\|/, $a);
@b = split(/\|/, $b);
$a[3] <=> $b[3];
}

sub dienice {
my($msg) = @_;
print "<h2>Error</h2>\n";
print $msg;
exit;
}

KevinADC
04-07-2006, 02:20 AM
you probably could adapt an appraoch like the code you posted to your application, but here is how I would probably do it:

chomp(my @times = <DATA>);
my @sorted = map {$_->[0]}
sort {$a->[1] <=> $b->[1]}
map{/(\d+):(\d+):(\d+)hrs/;[$_,$1.$2.$3]} @times;
print map {"$_$/"} @sorted;
__DATA__
00:00:58hrs
00:01:00hrs
19:01:01hrs
12:59:59hrs
23:59:59hrs
02:30:30hrs
11:30:30hrs
12:30:30hrs
00:59:59hrs

FishMonger
04-07-2006, 04:25 AM
It's been a long day for me, but unless I'm missing something, a simple sort of the array would produce the same sort order.

chomp(my @times = <DATA>);
my @sorted = sort @times;
print $_,$/ for @sorted;

__DATA__
00:00:58hrs
00:01:00hrs
19:01:01hrs
12:59:59hrs
23:59:59hrs
02:30:30hrs
11:30:30hrs
12:30:30hrs
00:59:59hrs
results:
00:00:58hrs
00:01:00hrs
00:59:59hrs
02:30:30hrs
11:30:30hrs
12:30:30hrs
12:59:59hrs
19:01:01hrs
23:59:59hrs

KevinADC
04-07-2006, 05:14 AM
You know, I think you're right, that will work just fine for sorting them as strings instead of digits. Good catch.

ivernrawks
04-19-2006, 04:22 AM
I have the codes for my previous sortings. I tried sorting for A-Z and 0-23. However it works only for A to Z but the time sorting does not work. I wonder why?

FishMonger
04-19-2006, 06:41 AM
This tread is getting a little long and might be hard for others to follow. It might be easier/best for all of us if you start a new thread/question and post your current script and detailed explaination of the problem.