I am reading in log data with the following time stamp format:
Sat Aug 07 04:42:21 2010
I want to convert it to something like this:
20100807044221
What is the best way to do this in perl? Thanks.
Use Time::Piece. (Core module since Perl 5.10.)
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
my $timestamp1 = 'Sat Aug 07 04:42:21 2010';
my $time = Time::Piece->strptime($timestamp1, '%a %b %d %H:%M:%S %Y');
my $timestamp2 = $time->strftime('%Y%m%d%H%M%S');
Date::Parse may not be installed on all your systems, so you may want to use the following snippet:
my ($sec, $min, $hour, $mday, $mon, $year) = localtime();
my $timestamp = sprintf( "%04d%02d%02d%02d%02d%02d",
$year+1900, $mon+1, $mday, $hour, $min, $sec);
print("Timestamp: $timestamp\n");
Timestamp: 20100819135418
This is what Date::Parse is for.
You specify language and corresponding date format, like (copied from the documentation):
$lang = Date::Language->new('German');
$lang->str2time("25 Jun 1996 21:09:55 +0100");
The above will return "epoch" value, AKA unix time value (what you need).
Edit: regarding your post, you only need the canonical date string like yyyy-mmm-ddd etc., therefore you can invoke POSIX::strftime for that. Furthermore, your date format is default, so you won't need the language call:
...
use Date::Parse;
use POSIX qw(strftime);
my $sec = str2time('Sat Aug 07 04:42:21 2010');
my $ymd = strftime "%Y%m%d%H%M%S", gmtime($sec);
print "$ymd\n";
...
Result:
20100807024221
Regards
rbo
perl -MPOSIX -le'print strftime "%Y%m%d%H%M%S", localtime'
never mind, you need to parse it first. that'll just print it out in your format.
Related
I am working on some training material for new programmers where I am talking about the HTTP Header, so I am trying to set the Last-Modified manually. I have everything worked out except for getting the file time to GMT. Below is what I have so far:
The question is: giving stat($fh)->mtime which could be running in any timezone, what code needs to be added to convert to GMT?
my $scriptFilename = $ENV{'SCRIPT_FILENAME'};
my $timestamp;
my $fh = FileHandle->new;
if ($fh->open("< ${scriptFilename}")) {
$timestamp = time2str("%a, %e %b %Y %X %Z", stat($fh)->mtime);
$fh->close;
}
#Last-Modified: Tue, 15 Oct 2019 12:45:26 GMT
print <<"END";
Content-type: text/html; charset=iso-8859-1
Last-Modified: $timestamp
<html>
...
</html>
time2str from the Date::Format package (I assume that's where time2str comes from) takes an optional 3rd argument to specify the timezone.
$timestamp = time2str("%a, %e %b %Y %X %Z", stat($fh)->mtime, 'UTC');
There seems to be some confusion here: the result of mtime is not in any time zone, it is in seconds since the epoch which is a fixed point in time (barring leap seconds which are ignored). Thus all you need to do is represent it in the time zone you want, which is UTC. Another answer mentioned how to do this with the function you had been using, but the usual function to format a time into a string is strftime, which is provided by a couple core modules.
use strict;
use warnings;
use POSIX 'strftime';
# gmtime interprets the mtime seconds in UTC
my $timestamp = strftime "%a, %e %b %Y %X %Z", gmtime $mtime;
use Time::Piece 'gmtime';
my $timestamp = gmtime($mtime)->strftime("%a, %e %b %Y %X %Z");
But your use case is actually a specific date format, the one the HTTP protocol uses, and which will always be in GMT/UTC. There is a module for that: HTTP::Date
use strict;
use warnings;
use HTTP::Date 'time2str';
my $timestamp = time2str $mtime;
Basically
my $dt = DateTime->new(
year => 2000,
month => 5,
day => 10,
hour => 15,
minute => 15,
time_zone => 'America/Los_Angeles',
);
print $dt->hour; # prints 15
$dt->set_time_zone( 'America/Chicago' );
print $dt->hour; # prints 17
See here for how to format the output.
I have to convert the GMT date to region specific date with format like "YYYY-MM-DD H:M:S".
Code developed is :-
use Time::Local;
($year,$mon,$day) = split /\-/, $ARGV[0];
($hrs,$min,$sec ) = split /:/, $ARGV[1];
$time = timegm( $sec, $min, $hrs, $day, $mon-1, $year-1900);
print scalar localtime($time), "\n";
But when I run it like :-
$ perl testDateGMTToLocal.pl 2018-10-29 11:49:33
It gives o/p converted in local time zone:-
Mon Oct 29 07:49:33 2018
But I want this o/p in below format
29-OCT-18 07:49:33
Thanks in advance.
I'd recommend to do it all using modules. The all-capable and very complete module is DateTime, and for this job you'd also need DateTime::Format::Strptime.
One other option is the simpler and much smaller core module Time::Piece
use warnings;
use strict;
use feature 'say';
use Time::Piece;
die "Usage $0 YYYY-MM-DD H:M:S" if #ARGV != 2;
my $time = join ' ', #ARGV;
my $tp = Time::Piece->strptime($time, "%Y-%m-%d %T");
my $local = localtime($tp->epoch);
say $local;
# In the desired format
say join('-', $local->mday, uc $local->month, $local->yy),
' ', $local->hms;
# If "Oct" is ok instead of block capitals for month abbreviation
say $local->strftime("%d-%b-%y %T");
This converts GMT time, with invocation as in the question, to the local time on my machine
Mon Oct 29 04:09:33 2018
29-OCT-18 04:09:33
29-Oct-18 04:09:33
where the middle one was asked for.
On some systems there is the %F format specifier for %Y-%m-$d.† There may be a defined format for 29-OCT-18, in which case you don't have to patch it by hand, but I am not aware of it.
† Or the module has its own formatting in which case that's portable. But origin of the error when it fails to do %F on my system isn't clear to me in that sense.
You can use
use POSIX qw( strftime );
print(strftime("%d-%b-%y %H:%M:%S", localtime($time)), "\n");
Input:
$str="Thu Mar 25 01:48:45 IST 2011";
Desired output:
2011-03-25
I want only date, not the time.
#!/usr/bin/env perl
use strict;
use warnings;
use Time::Piece;
my $tstamp = Time::Piece->strptime
("Thu Mar 25 01:48:45 2011", "%a %b %d %H:%M:%S %Y");
print $tstamp->strftime("%Y-%m-%d\n");
use Date::Manip;
$str =~ s/[[:upper:]]{3}//; # Remove timezone
$d = ParseDate($str);
die "Invalid date\n" unless $d;
$d=~s/(....)(..)(..).*/$1-$2-$3/;
print "$d\n";
Heck, if you know the format of the date, you don't even need to use a Perl module to manipulate the date and time:
my %months = (Jan => 1, Feb => 2, Mar => 3, Apr => 4 ...);
my $st r= "Thu Mar 25 01:48:45 IST 2011";
$st =~! /\S+\s+(\S+)\s+(\S+)\s+\S+\s+\S+(\S+)/;
my $date = sprintf "%s-%02s-%02s", $3, $months{$1}, $2;
Okay, this is very error prone, and you probably want to do a lot of error checking. The regular expression I used could be formatted a bit stronger (checking for characters and numbers instead of just "not white space". And, you probably want to make sure the month is valid too.
Actually, you're better off using a Date/Time module to do this. I was going to recommend Time::Piece, but James_R_Ferguson beat me to it.
How to convert date in text format:
23.10.2011 11:35:00
to timestamp ?
Using Time::Local , you can do:
use Time::Local;
my $date = '23.10.2011 11:35:00';
my ($mday,$mon,$year,$hour,$min,$sec) = split(/[\s.:]+/, $date);
my $time = timelocal($sec,$min,$hour,$mday,$mon-1,$year);
print $time,"\n",scalar localtime $time;
Output:
1319362500
Sun Oct 23 11:35:00 2011
I'd look into DateTime and the parsing modules.
perl -MDateTime::Format::Strptime -le'$strp = DateTime::Format::Strptime->new( pattern => "%d.%m.%Y %T", time_zone => "local"); $dt = $strp->parse_datetime("23.10.2011 11:35:00"); print $dt->epoch'
1319384100 at -e line 1.
Same as above, but not a one-liner:
use DateTime::Format::Strptime;
my $strp = DateTime::Format::Strptime->new(
pattern => '%d.%m.%Y %T',
time_zone => 'local',
);
my $dt = $strp->parse_datetime('23.10.2011 11:35:00');
print $dt->epoch;
Using Date::Parse in Perl is very elegante option too.
Maybe someone will found this useful:
$gmtdate = 'Jul 12 00:12:26 2021 GMT';
my $timestamp = str2time($gmtdate);
Not sure why the Time::Piece answer was deleted. Maybe because it (Time::Piece) has its quirks. But it's more powerful than Date::Parse (although less powerful than DateTime, but some say it covers most of the needs), it's a core module, and you don't have to parse the string as with Time::Local. But datetime math is apparently not DST-safe.
Long story short:
use Time::Piece;
my $tp = Time::Piece->strptime("23.10.2011 11:35:00",
"%d.%m.%Y %H:%M:%S");
# or this way (if the timestamp is in the local time zone):
# $tp = localtime->strptime("23.10.2011 11:35:00",
# "%d.%m.%Y %H:%M:%S");
print $tp;
More on creating Time::Piece objects here.
I need to read the system clock (time and date) and display it in a human-readable format in Perl.
Currently, I'm using the following method (which I found here):
#!/usr/local/bin/perl
#months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
#weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
$year = 1900 + $yearOffset;
$theTime = "$hour:$minute:$second, $weekDays[$dayOfWeek] $months[$month] $dayOfMonth, $year";
print $theTime;
When you run the program, you should see a much more readable date and time like this:
9:14:42, Wed Dec 28, 2005
This seems like it's more for illustration than for actual production code. Is there a more canonical way?
Use localtime function:
In scalar context, localtime() returns
the ctime(3) value:
$now_string = localtime; # e.g., "Thu Oct 13 04:54:34 1994"
You can use localtime to get the time and the POSIX module's strftime to format it.
While it'd be nice to use Date::Format's and its strftime because it uses less overhead, the POSIX module is distributed with Perl, and is thus pretty much guaranteed to be on a given system.
use POSIX;
print POSIX::strftime( "%A, %B %d, %Y", localtime());
# Should print something like Wednesday, January 28, 2009
# ...if you're using an English locale, that is.
# Note that this and Date::Format's strftime are pretty much identical
As everyone else said "localtime" is how you tame date, in an easy and straight forward way.
But just to give you one more option. The DateTime module. This module has become a bit of a favorite of mine.
use DateTime;
my $dt = DateTime->now;
my $dow = $dt->day_name;
my $dom = $dt->mday;
my $month = $dt->month_abbr;
my $chr_era = $dt->year_with_christian_era;
print "Today is $dow, $month $dom $chr_era\n";
This would print "Today is Wednesday, Jan 28 2009AD". Just to show off a few of the many things it can do.
use DateTime;
print DateTime->now->ymd;
It prints out "2009-01-28"
Like someone else mentioned, you can use localtime, but I would parse it with Date::Format. It'll give you the timestamp formatted in pretty much any way you need it.
The simplest one-liner print statement to print localtime in clear, readable format is:
print scalar localtime (); #Output: Fri Nov 22 14:25:58 2019