date format

S

spross

hi

sorry, i'm a beginner :)
i have a file and the first line looks like:

%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%

my question: how chan i get the date in this header in a format like:
YYYYMMDD

thanks for help!
spross
 
J

Josef Moellers

spross said:
hi

sorry, i'm a beginner :)
i have a file and the first line looks like:

%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%

my question: how chan i get the date in this header in a format like:
YYYYMMDD

What have you tried so far and where did it fail?

Please post the code that you think should do the work and we'll comment
and help.
 
B

Bart Van der Donck

spross said:
sorry, i'm a beginner :)
i have a file and the first line looks like:

%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%

my question: how chan i get the date in this header in a format like:
YYYYMMDD

#!perl
use strict;
use warnings;
my $file =
'%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%
1111111111111111111111
2222222222222222222222
3333333333333333333333
';
my @m = ('Jan', 'Feb', 'Mar', 'Apr', 'May',
'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
my @ar = split / /, (split /\n/, $file)[0];
$ar[3] =~ s/$m[$_]/@{[sprintf('%02g',$_+1)]}/ for (0..$#m);
die "Can't find month '$ar[3]'\n" unless $ar[3]=~/^(0|1)[0-9]$/;
print $ar[7], $ar[3], sprintf('%02g',$ar[4]);

__END__

Hope this helps,
 
J

John W. Krahn

spross said:
sorry, i'm a beginner :)
i have a file and the first line looks like:

%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%

my question: how chan i get the date in this header in a format like:
YYYYMMDD

$ perl -le'
$_ = q[%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%];
print;
my %mons = qw/
Jan 1 Feb 2 Mar 3 Apr 4 May 5 Jun 6
Jul 7 Aug 8 Sep 9 Oct 10 Nov 11 Dec 12
/;
/ \s
(?: Mon | Tue | Wed | Thu | Fri | Sat | Sun )
\s+
( @{[ join q[|], keys %mons ]} )
\s+
( \d\d? )
\s+
\d{2} : \d{2} : \d{2}
\s+
\S+
\s+
( \d{4} )
\s
/x && ( $_ = sprintf q[%04d%02d%02d], $3, $mons{ $1 }, $2 );
print;
'
%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%
20060616



John
 
M

Mumia W.

spross said:
hi

sorry, i'm a beginner :)
i have a file and the first line looks like:

%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%

my question: how chan i get the date in this header in a format like:
YYYYMMDD

thanks for help!
spross

Use Date::parse and Date::Format:

use Date::parse qw(str2time);
use Date::Format qw(time2str);

local $_ = q{
%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%
};

if (m/HEADER ([^%]+)/) {
my $time = str2time($1);
print "\$time = $time\n";
print time2str("%Y%m%d", $time);
}


HTH
 
I

Ian Wilson

Bart said:
spross wrote:

sorry, i'm a beginner :)
i have a file and the first line looks like:

%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%

my question: how chan i get the date in this header in a format like:
YYYYMMDD


#!perl
use strict;
use warnings;
my $file =
'%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%
1111111111111111111111
2222222222222222222222
3333333333333333333333
';
my @m = ('Jan', 'Feb', 'Mar', 'Apr', 'May',
'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
my @ar = split / /, (split /\n/, $file)[0];
$ar[3] =~ s/$m[$_]/@{[sprintf('%02g',$_+1)]}/ for (0..$#m);
die "Can't find month '$ar[3]'\n" unless $ar[3]=~/^(0|1)[0-9]$/;
print $ar[7], $ar[3], sprintf('%02g',$ar[4]);

__END__

Hope this helps,

I'm not a beginner and I found this example rather obscure and hard to
understand. Perl needn't look that much like line noise IMO.

I'd put the data in a DATA section since it gives a structure
'while(<>){}' that is closer to the way most peaple read data files.

I'd use meaningful variable names since the OP claims to be a beginner
(though I think they're a good idea no matter your level of experience)

Here's how I would do it ...

#!/usr/bin/perl
use strict;
use warnings;
my $i = 1;
my %monthno = map {$_, $i++}
qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
while(<DATA>) {
if (/HEADER \w+ (\w+) (\d+) \d+:\d+:\d+ \w+ (\d+)/) {
die "unknown month name $1" unless $monthno{$1};
printf ("%4d%.2d%2d\n", $3, $monthno{$1}, $2);
}
}
__DATA__
%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%
1111111111111111111111
2222222222222222222222
3333333333333333333333
%%%%%%%% HEADER Fri Foo 16 17:21:03 MEST 2006 %%%%%%%%%%%%


Doubtless it can be improved in many ways (and I, for one, would be
interested to see how). I nearly named $i as $index but for me the
purpose and content of $i is clear enough.
 
A

anno4000

[previous solution snipped]
I'm not a beginner and I found this example rather obscure and hard to
understand. Perl needn't look that much like line noise IMO.

I'd put the data in a DATA section since it gives a structure
'while(<>){}' that is closer to the way most peaple read data files.

I'd use meaningful variable names since the OP claims to be a beginner
(though I think they're a good idea no matter your level of experience)

Here's how I would do it ...

#!/usr/bin/perl
use strict;
use warnings;
my $i = 1;
my %monthno = map {$_, $i++}
qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
while(<DATA>) {
if (/HEADER \w+ (\w+) (\d+) \d+:\d+:\d+ \w+ (\d+)/) {
die "unknown month name $1" unless $monthno{$1};
printf ("%4d%.2d%2d\n", $3, $monthno{$1}, $2);
}
}
__DATA__
%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%
1111111111111111111111
2222222222222222222222
3333333333333333333333
%%%%%%%% HEADER Fri Foo 16 17:21:03 MEST 2006 %%%%%%%%%%%%


Doubtless it can be improved in many ways (and I, for one, would be
interested to see how). I nearly named $i as $index but for me the
purpose and content of $i is clear enough.

In production code I would provide a smaller scope for $i. "do" blocks
can be handy for that (untested):

my %monthno = do {
my $i = 0;
map { $_ => ++ $i }
qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
};

Alternatively, one of the date/time modules from CPAN could be used.
I happen to have Date::parse around.

use Date::parse qw( strptime);

my $line = "%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%";
my ($day,$month,$year) = (strptime( $line =~ /% HEADER (.*) %/))[ 3 .. 5];
printf "%4d%02d%02d\n", $year + 1900, $month + 1, $day;

Anno
 
B

Bart Van der Donck

Ian said:
Bart said:
[...]
#!perl
use strict;
use warnings;
my $file =
'%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006
%%%%%%%%%%%%
1111111111111111111111
2222222222222222222222
3333333333333333333333
';
my @m = ('Jan', 'Feb', 'Mar', 'Apr', 'May',
'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
my @ar = split / /, (split /\n/, $file)[0];
$ar[3] =~ s/$m[$_]/@{[sprintf('%02g',$_+1)]}/ for (0..$#m);
die "Can't find month '$ar[3]'\n" unless $ar[3]=~/^(0|1)[0-9]$/;
print $ar[7], $ar[3], sprintf('%02g',$ar[4]);

__END__

Hope this helps,

I'm not a beginner and I found this example rather obscure and hard to
understand. Perl needn't look that much like line noise IMO.

I think you've entered the domain of personal preferences here. As far
as I'm concerned, my code doesn't read as line noise (I can easliy
follow it, but hey, that's me).

I for one have more difficulty to follow Mr Krahn's code, as I'm not
too confident with some of his techniques... But I do think that his
code will be perceived as more obscure by a beginner when you juxtapose
it next to mine.

But of course I do like occasional "sport lines" like

$ar[3] =~ s/$m[$_]/@{[sprintf('%02g',$_+1)]}/ for (0..$#m);

in stead of splitting it up in 5 lines or so, like I would rather do in
production code. Just do myself a favour in the future :)
I'd put the data in a DATA section since it gives a structure
'while(<>){}' that is closer to the way most peaple read data files.

I agree, that would have been better indeed.
I'd use meaningful variable names since the OP claims to be a beginner
(though I think they're a good idea no matter your level of experience)

$file = file
@ar short for array (which isn't descriptive for its content of course,
but the content of that array is not univocal here anyway)
@m short for @months

Well, yes, when written in full they would become more meaningful I
suppose...
 
I

Ian Wilson

Bart said:
But of course I do like occasional "sport lines" like

$ar[3] =~ s/$m[$_]/@{[sprintf('%02g',$_+1)]}/ for (0..$#m);

in stead of splitting it up in 5 lines or so, like I would rather do in
production code. Just do myself a favour in the future :)

Yes, so far as I can tell, the above is identical to

my $i = 0;
$ar[3] =~ s/$_/sprintf "%02g",++$i/e for (@m);

using s///e instead of s//@{[]}/
and using the array more like a list.


With didactic variable names ...

my $monthnumber = 0;
foreach my $monthname (@monthnames){
$line =~s/$monthname/sprintf "%02g", ++$monthnumber/e;
};

Which, personally, I do prefer :)
 
A

axel

Bart Van der Donck said:
spross wrote:
#!perl
use strict;
use warnings;
my $file =
'%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%
1111111111111111111111
2222222222222222222222
3333333333333333333333
';
my @m = ('Jan', 'Feb', 'Mar', 'Apr', 'May',
'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
my @ar = split / /, (split /\n/, $file)[0];
$ar[3] =~ s/$m[$_]/@{[sprintf('%02g',$_+1)]}/ for (0..$#m);
die "Can't find month '$ar[3]'\n" unless $ar[3]=~/^(0|1)[0-9]$/;
print $ar[7], $ar[3], sprintf('%02g',$ar[4]);

It seems a bit overcomplicated :)

#!/usr/bin/perl

use strict;
use warnings;

my $s ='%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%';

my %mon = (Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5,
Jun => 6, Jul => 7, Aug => 8, Sep => 9, Oct => 10,
Nov => 11, Dec => 12);

my ($month, $date, $year) = (split ' ', $s)[3, 4, 7];
printf ("%.4d%.2d%.2d\n", $year, $mon{$month}, $date);

__END__


Axel
 
J

John W. Krahn

Bart said:
spross said:
sorry, i'm a beginner :)
i have a file and the first line looks like:

%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%

my question: how chan i get the date in this header in a format like:
YYYYMMDD

#!perl
use strict;
use warnings;
my $file =
'%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%
1111111111111111111111
2222222222222222222222
3333333333333333333333
';
my @m = ('Jan', 'Feb', 'Mar', 'Apr', 'May',
'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
my @ar = split / /, (split /\n/, $file)[0];

A lot of date formats use a leading space for single digit days so splitting
on a single space character will give you an off-by-one error on the day and
year fields.

$ar[3] =~ s/$m[$_]/@{[sprintf('%02g',$_+1)]}/ for (0..$#m);

Is there a good reason to use a floating-point format ('g') instead of an
integer format ('i', 'd' or 'u')?

die "Can't find month '$ar[3]'\n" unless $ar[3]=~/^(0|1)[0-9]$/;

Why use an alternation with capturing parentheses instead of a character
class? Where do you use the value stored in $1?

print $ar[7], $ar[3], sprintf('%02g',$ar[4]);



John
 
J

John W. Krahn

Bart said:
spross said:
sorry, i'm a beginner :)
i have a file and the first line looks like:

%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%

my question: how chan i get the date in this header in a format like:
YYYYMMDD

#!perl
use strict;
use warnings;
my $file =
'%%%%%%%% HEADER Fri Jun 16 17:21:03 MEST 2006 %%%%%%%%%%%%
1111111111111111111111
2222222222222222222222
3333333333333333333333
';
my @m = ('Jan', 'Feb', 'Mar', 'Apr', 'May',
'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
my @ar = split / /, (split /\n/, $file)[0];

A lot of date formats use a leading space for single digit days so splitting
on a single space character will give you an off-by-one error on the day and
year fields.

$ar[3] =~ s/$m[$_]/@{[sprintf('%02g',$_+1)]}/ for (0..$#m);

Is there a good reason to use a floating-point format ('g') instead of an
integer format ('i', 'd' or 'u')?

die "Can't find month '$ar[3]'\n" unless $ar[3]=~/^(0|1)[0-9]$/;

Why use an alternation with capturing parentheses instead of a character
class? Where do you use the value stored in $1? So you are saying that 19 is
a valid month?

print $ar[7], $ar[3], sprintf('%02g',$ar[4]);



John
 
B

Bart Van der Donck

John said:
[...]
A lot of date formats use a leading space for single digit days so splitting
on a single space character will give you an off-by-one error on the day and
year fields.

Yes, I think I remember there was something tricky with it, that's why
I did sprintf('%02g',$ar[4]); in stead of just print $ar[4] in my
program. Thanks for pointing that out, the solution is simple:

my @ar = split / +/, (split /\n/, $file)[0];
$ar[3] =~ s/$m[$_]/@{[sprintf('%02g',$_+1)]}/ for (0..$#m);

Is there a good reason to use a floating-point format ('g') instead of an
integer format ('i', 'd' or 'u')?

Well, it's there to guarantee the two-digit MM (month) format. I don't
see any drawbacks for that here, but maybe I'm not fully aware of the
exact finetunings of this construction.
die "Can't find month '$ar[3]'\n" unless $ar[3]=~/^(0|1)[0-9]$/;

Why use an alternation with capturing parentheses instead of a character
class? Where do you use the value stored in $1? So you are saying that 19 is
a valid month?

You're right, something like

die "..." unless $ar[3]=~ /^0[1-9]$|^1[0-2]$/;

should do.

Thanks for your comment. I learnt from it.
 
J

John W. Krahn

Bart said:
John said:
$ar[3] =~ s/$m[$_]/@{[sprintf('%02g',$_+1)]}/ for (0..$#m);
Is there a good reason to use a floating-point format ('g') instead of an
integer format ('i', 'd' or 'u')?

Well, it's there to guarantee the two-digit MM (month) format. I don't
see any drawbacks for that here, but maybe I'm not fully aware of the
exact finetunings of this construction.

The array index (0..$#m) will always be an integer. The underlying C library
uses type promotion so the integer will be converted to a double
floating-point number in order to convert it to a string. If the integer is
large enough it will be converted using scientific notation:

$ perl -le'print for $^T, sprintf( q[%02g], $^T ), sprintf q[%02d], $^T'
1152186353
1.15219e+09
1152186353


John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,197
Messages
2,571,040
Members
47,635
Latest member
SkyePurves

Latest Threads

Top