Military type format date/time conversion

Hello All,

I have a requirement to convert a 12 hour format to 24 hour time format and the sample input /out put is below

Input Time format : Nov 2 2011 12:16AM
Out Put Format : Nov 2 2011 0:16

Input : Nov 2 2011 4:16PM
Out Put: Nov 2 2011 16:16

I have done this using a perl script and working absolutely fine -
###############

use strict;

while( my $line = <DATA> ){
 $line =~ s/(\d+)(:\d+)(A|P)\.M\,/($3 eq 'a')?($1%12).$2:($1%12+12).$2/e;
 print $line;
}

__DATA__
Nov 2 2011 12:41A.M,
Nov 2 2011 12:41A.M,
Nov 2 2011  3:41P.M,
Nov 2 2011  5:41P.M,

###################OUT PUT#############

Nov 2 2011 12:41
Nov 2 2011 12:41
Nov 2 2011 15:41
Nov 2 2011 17:41

My requirement is now :
1) I have file with thousands of records like below and i want to convert each of the records with right time format as i mentioned above.

Nov 2 2011 12:01AM,52893,420,1,4,0,52834,4,1208,67664942,603459924403.0,1,150054,1208,3
Nov 2 2011 5:16PM,52127,420,1,4,0,52122,4,1429,55943831,603459924406.0,1,150054,1429,3

I need to convert the first column match (12:01AM/5:16PM) and convert this to right format

Expected output is :

Nov 2 2011 0:01,52893,420,1,4,0,52834,4,1208,67664942,603459924403.0,1,150054,1208,3
Nov 2 2011 17:16,52127,420,1,4,0,52122,4,1429,55943831,603459924406.0,1,150054,1429,3

I know with little modification to my script this can be acheived but i am not able to match the entire record with regx.

ANY HELP IS MUCH APPRICIATED.

Here is one way:

sed 's/.* \(.*[AP]M\).*/\1/' File

you hardly need to match the entire line, especially when the data comes in a convenient tabular format. awk is made for this.

$ cat 24hr.awk

BEGIN { FS=","; OFS="," }
{
        split($1, A, " ");        split(A[4], B, ":");

        HR=B[1];
        MIN=substr(B[2], 0, 2);
        AM=substr(B[2], 3);

        if(AM == "PM")  HR += 12;

        $1=sprintf("%s %s %s %02d:%02d", A[1], A[2], A[3], HR, MIN);
} 1

$ awk -f 24hr.awk < data

Nov 2 2011 12:01,52893,420,1,4,0,52834,4,1208,67664942,603459924403.0,1,150054,1208,3
Nov 2 2011 17:16,52127,420,1,4,0,52122,4,1429,55943831,603459924406.0,1,150054,1429,3

$

Thanks but i need the entire records - not the date/time part and also your out put has AM/PM which is not needed .

Ex. Input records :
Nov 2 2011 12:01AM,52893,420,1,4,0,52834,4,1208,67664942,603459924403.0,1,150054,1208,3
Nov 2 2011 5:05PM,52127,420,1,4,0,52122,4,1283,151823875,603459924404.0,1,150054,1283,3

Expected out put records:

Nov 2 2011 12:01,52893,420,1,4,0,52834,4,1208,67664942,603459924403.0,1,150054,1208,3
Nov 2 2011 17:05,52127,420,1,4,0,52122,4,1283,151823875,603459924404.0,1,150054,1283,3

If my perl script can be modified to match the records or same sed command equivalent than it will be fine.

A correction for the 12:... to 0:... fix:

$ cat 24hr.awk

BEGIN { FS=","; OFS="," }

{      # Split "Nov 2 2011 12:01AM" into A[1]="Nov", A[2]="2", A[3]="2011", A[4]="12:01AM"
        split($1, A, " ");
        # Split "12:01AM" into B[1]="12", B[2]="01AM"
        split(A[4], B, ":");

        HR=B[1];
        MIN=substr(B[2], 0, 2); # Get "01" out of "01AM"
        AM=substr(B[2], 3); # Get "AM" out of "01AM"

        HR %= 12;
        if(AM == "PM")  HR+=12;
        # Put the data we want back into first field the way we want it.
        $1=sprintf("%s %s %s %d:%02d", A[1], A[2], A[3], HR, MIN);
} 1 # Always print the entire line.

$ awk -f 24hr.awk < data
Nov 2 2011 0:01,52893,420,1,4,0,52834,4,1208,67664942,603459924403.0,1,150054,1208,3
Nov 2 2011 17:16,52127,420,1,4,0,52122,4,1429,55943831,603459924406.0,1,150054,1429,3

$

Excellent @Corona Thanks much for your time

What you already have works, you just need to tweak your regex:

#!/usr/bin/env perl

use strict;

my $line;

while($line = <DATA>) {
    $line =~ s/(\d+)(:\d+)(A|P)M\,/($3 eq 'a')?($1%12).$2:($1%12+12).$2/e;
    chomp($line);
    print "$line\n";
}

exit(0);

__DATA__
Nov 2 2011 12:01AM,52893,420,1,4,0,52834,4,1208,67664942,603459924403.0,1,150054,1208,3
Nov 2 2011 5:16PM,52127,420,1,4,0,52122,4,1429,55943831,603459924406.0,1,150054,1429,3

Output:

Nov 2 2011 12:0152893,420,1,4,0,52834,4,1208,67664942,603459924403.0,1,150054,1208,3
Nov 2 2011 17:1652127,420,1,4,0,52122,4,1429,55943831,603459924406.0,1,150054,1429,3

Basically removing the '.' before the 'M' from you regex will do it.