I want to get the system clock (time and date) and display it in a human-readable format in Perl.
The format like 2014-09-12 15:13:56
#!/usr/local/bin/perl
my %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;
$now = "$year-$months-$dayOfMonth $hour:$minute:$second";
print $now;
When you run the program, you should see a much more readable date and time like this:
2014--12 16:57:15
how to get convert the month to number ?
Using Time::Piece (core module since perl v5.9.5)
use Time::Piece;
my $dt = localtime;
print $dt->ymd, " ", $dt->hms, "\n";
using DateTime
use DateTime;
my $dt = DateTime->now();
print $dt->ymd, " ", $dt->hms, "\n";
It's easier using a Perl module (POSIX doesn't requires installation):
use POSIX qw/strftime/;
my $now_string = strftime "%Y-%m-%d %H:%M:%S", localtime;
print $now_string, "\n"; #<-- prints: 2014-09-12 11:09:45 (with my local time)
Regarding to your code, there is a typo:
$now = "$year-$months-$dayOfMonth $hour:$minute:$second";
should be:
$now = "$year-$month-$dayOfMonth $hour:$minute:$second";
Be sure to write use strict; and use warnings; in the top place of your script. It prevents you from errors like that.
I like to put these date and time tasks into functions for reuse.
Here is my approach:
use strict;
use warnings;
my $time_stamp = getTodaysDateTime();
print "Program Started: $time_stamp \n";
# do some processing
$time_stamp = getTodaysDateTime();
print "Program Ended: $time_stamp \n";
# return date in specific format
# ex: 2014-09-12 14:11:43
sub getTodaysDateTime {
my ($sec,$min,$hour,$mday,$mon,$year,
$wday,$yday,$isdst) = localtime(time);
$year += 1900;
$mon += 1;
return sprintf("%d-%02d-%02d %02d:%02d:%02d",
$year,$mon,$mday,$hour,$min,$sec);
}
Related
I am trying to convert hex time(getting first output from kernel module) into nanosecond granularity,
580a9272.0a9ce167
and I am trying to convert it using perl into human readable format:
while (<>) {
s/^([a-fA-F0-9]+)(\.)([a-fA-F0-9]+)(\s+.*)/sprintf("%s%s%s%s",&$converter(hex($1)), $2, hex($3), $4)/oe;
} continue {
print;
}
output : Fri Oct 21 18:10:58 2016.178053479
Converter uses localtime() and gmtime() directly
I want time with nano granularity and then year.Any help is highly appreciated.
POSIX::strftime doesn't support fractional seconds, so you need to build the output in parts.
use POSIX qw( strftime );
my $opt_gmt = 1;
my $hex = '580a9272.0a9ce167';
my ($s, $ns) = map hex($_), split /\./, $hex;
my $formatted_ns = sprintf("%09d", $ns);
my $formatted = strftime("%a %b %d %H:%M:%S.$formatted_ns %Y",
defined($opt_gmt) ? gmtime($s) : localtime($s));
say $formatted; # Fri Oct 21 22:10:58.178053479 2016
DateTime has native support for nanoseconds, so that presents an alternative.
use DateTime qw( );
my $opt_gmt = 1;
my $hex = '580a9272.0a9ce167';
my ($s, $ns) = map hex($_), split /\./, $hex;
my $dt = DateTime->from_epoch( epoch => $s );
$dt->set_nanosecond( $ns );
$dt->set_time_zone( defined($opt_gmt) ? 'UTC' : 'local' );
say $dt->strftime("%a %b %d %H:%M:%S.%N %Y"); # Fri Oct 21 22:10:58.178053479 2016
i want to convert the date time format to that i want.
how to convert the date time format from Fri Nov 21 2014 15:04:32 to 2014-11-21 15:04:32 ?
thanks
Time::Piece has been core Perl for many years.
Use strptime (string parse time) to parse your date/time string.
Use strftime (string format time) to format your date/time as you want it.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Time::Piece;
# Formats are defined in "man strftime"
my $in_fmt = '%a %b %d %Y %H:%M:%S';
my $out_fmt = '%Y-%m-%d %H:%M:%S';
my $in_date = 'Fri Nov 21 2014 15:04:32';
my $date = Time::Piece->strptime($in_date, $in_fmt);
my $out_date = $date->strftime($out_fmt);
say $out_date;
my $str = 'Fri Nov 21 2014 15:04:32';
my #months =('jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec');
my ($day,$mon,$date,$year,$time) = split(' ',lc($str));
my %month_hash;
#month_hash{#months} = (1 .. 12);
print "$year-$month_hash{$mon}-$date $time";
try this its crude method but works for your requirements. use date::manip for flexible usage
Here i based one problem.. i have two timestamps with same format like (Tue Dec 14 18:23:19 2010 & Tue Dec 14 17:23:19 2010). how can i get the difference of two timestamps in hours.
please help me
use Date::Parse;
my $t1 = 'Tue Dec 14 17:23:19 2010';
my $t2 = 'Tue Dec 14 18:23:19 2010';
my $s1 = str2time( $t1 );
my $s2 = str2time( $t2 );
print $s2 - $s1, " seconds\n";
I use the DateTime family of classes for pretty much all of my date/time handling.
#!/usr/bin/perl
use strict;
use warnings;
use DateTime::Format::Strptime;
my $dp = DateTime::Format::Strptime->new(
pattern => '%a %b %d %H:%M:%S %Y'
);
# Create two DateTime objects
my $t1 = $dp->parse_datetime('Tue Dec 14 17:23:19 2010');
my $t2 = $dp->parse_datetime('Tue Dec 14 18:23:19 2010');
# The difference is a DateTime::Duration object
my $diff = $t2 - $t1;
print $diff->hours;
You can take advantage of DateTime and its subtract_datetime() method, which returns a DateTime::Duration object.
use Date::Parse;
use DateTime;
my $t1 = 'Tue Dec 14 17:23:19 2010';
my $t2 = 'Tue Dec 14 18:23:19 2010';
my $t1DateTime = DateTime->from_epoch( epoch => str2time( $t1 ) );
my $t2DateTime = DateTime->from_epoch( epoch => str2time( $t2 ) );
my $diff = $t2DateTime->subtract_datetime( $t1DateTime );
print "Diff in hours: " . $diff->in_units('hours') . "\n";
print "Diff in months: " . $diff->in_units('months') . "\n";
How do I tweak this to get yesterday's date using localtime?
use strict;
sub spGetCurrentDateTime;
print spGetCurrentDateTime;
sub spGetCurrentDateTime {
my ($sec, $min, $hour, $mday, $mon, $year) = localtime();
my #abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
my $currentDateTime = sprintf "%s %02d %4d", $abbr[$mon], $mday, $year+1900; #Returns => 'Aug 17 2010'
return $currentDateTime;
}
~
use DateTime qw();
DateTime->now->subtract(days => 1);
The expression on the second line returns a DateTime object.
As tempting as it is to just subtract a day's worth of seconds from the current time, there are times when this will yield the wrong answer (leap seconds, DST, and possibly others). I find it easier to just let strftime (available in the Perl 5 core module POSIX) take care of all of that for me.
#!/usr/bin/perl
use strict;
use warnings;
use Time::Local;
use POSIX qw/strftime/;
#2010-03-15 02:00:00
my ($s, $min, $h, $d, $m, $y) = (0, 0, 0, 15, 2, 110);
my $time = timelocal $s, $min, $h, $d, $m, $y;
my $today = strftime "%Y-%m-%d %T", localtime $time;
my $yesterday = strftime "%Y-%m-%d %T", $s, $min, $h, $d - 1, $m, $y;
my $oops = strftime "%Y-%m-%d %T", localtime $time - 24*60*60;
print "$today -> $yesterday -> $oops\n";
The DST problem can be worked around by taking 3600s from midday today instead of the current time:
#!/usr/bin/perl
use strict;
use warnings;
use Time::Local;
sub spGetYesterdaysDate;
print spGetYesterdaysDate;
sub spGetYesterdaysDate {
my ($sec, $min, $hour, $mday, $mon, $year) = localtime();
my $yesterday_midday=timelocal(0,0,12,$mday,$mon,$year) - 24*60*60;
($sec, $min, $hour, $mday, $mon, $year) = localtime($yesterday_midday);
my #abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
my $YesterdaysDate = sprintf "%s %02d %4d", $abbr[$mon], $mday, $year+1900;
return $YesterdaysDate;
}
In light of the "unspecified" documented behaviour of the strftime solution suggested by Chas, this approach might be better if you're not able to test for expected-but-not-guaranteed results across multiple platforms.
use Time::Piece.
use strict;
use warnings;
use 5.010;
# These are core modules in Perl 5.10 and newer
use Time::Piece;
use Time::Seconds;
my $yesterday = localtime() - ONE_DAY;
say $yesterday->strftime('%b %d %Y');
Note that this can go wrong in certain borderline cases, such as the start of daylight saving time.
The following version does behave correct in such cases:
use strict;
use warnings;
use 5.010;
# These are core modules in Perl 5.10 and newer
use Time::Piece;
use Time::Seconds;
my $now = localtime();
my $yesterday = $now - ONE_HOUR*($now->hour + 12);
say $yesterday->strftime('%b %d %Y');
Alternatively, you can use the DateTime module as described in a different answer. That is not a core module, though.
Solution suggested by most users is wrong!
localtime(time() - 24*60*60)
The worst thing you can do is to assume that 1 day = 86400 seconds.
Example: Timezone is America/New_York, date is Mon Apr 3 00:30:00 2006
timelocal gives us 1144038600
localtime(1144038600 - 86400) = Sat Apr 1 23:30:00 EST 2006
oops!
The right and the only solution is to let system function normalize values
$prev_day = timelocal(0, 0, 0, $mday-1, $mon, $year);
Or let datetime frameworks (DateTime, Class::Date, etc) do the same.
That's it.
localtime(time() - 24*60*60)
my $yesterday = time();
$yesterday = $yesterday - (24*60*60);
24 as 24 hours, 60 as 60 minutes in hour and 60 as 60 seconds in minute
time() will return actual timestamp, and 246060 will remove seconds for exactly one day
After this simply do:
localtime($yesterday);
This is how I do it.
#!/usr/bin/perl
use POSIX qw(strftime);
$epoc = time();
$epoc = $epoc - 24 * 60 * 60;
$datestring = strftime "%F", localtime($epoc);
print "Yesterday's date is $datestring \n";
Using this function:
perl -e 'use Time::Local; print timelocal("00","00","00","01","01","2000"),"\n";'
It will return an epochtime - but only in GMT - if i want the result in GMT+1 (which is the systems localtime(TZ)), what do i need to change?
Thanks in advance,
Anders
use DateTime;
my $dt = DateTime->now;
$dt->set_time_zone( 'Europe/Madrid' );
There is only one standard definition for epochtime, based on UTC, and not different epochtimes for different timezones.
If you want to find the offset between gmtime and localtime, use
use Time::Local;
#t = localtime(time);
$gmt_offset_in_seconds = timegm(#t) - timelocal(#t);
While Time::Local is a reasonable solution, you may be better off using the more modern DateTime object oriented module. Here's an example:
use strict;
use DateTime;
my $dt = DateTime->now;
print $dt->epoch, "\n";
For the timezones, you can use the DateTime::TimeZone module.
use strict;
use DateTime;
use DateTime::TimeZone;
my $dt = DateTime->now;
my $tz = DateTime::TimeZone->new(name => "local");
$dt->add(seconds => $tz->offset_for_datetime($dt));
print $dt->epoch, "\n";
CPAN Links:
DateTime
You just need to set the timezone. Try:
env TZ=UTC+1 perl -e 'use Time::Local; print timelocal("00","00","00","01","01","2000"),"\n";'
Time::Local::timelocal is the inverse of localtime. The result will be in your host's local time:
$ perl -MTime::Local -le \
'print scalar localtime timelocal "00","00","00","01","01","2000"'
Tue Feb 1 00:00:00 2000
Do you want the gmtime that corresponds to that localtime?
$ perl -MTime::Local' -le \
'print scalar gmtime timelocal "00","00","00","01","01","2000"'
Mon Jan 31 23:00:00 2000
Do you want it the other way around, the localtime that corresponds to that gmtime?
$ perl -MTime::Local -le \
'print scalar localtime timegm "00","00","00","01","01","2000"'
Tue Feb 1 01:00:00 2000
An other example based on DateTime::Format::Strptime
use strict;
use warnings;
use v5.10;
use DateTime::Format::Strptime;
my $s = "2016-12-22T06:16:29.798Z";
my $p = DateTime::Format::Strptime->new(
pattern => "%Y-%m-%dT%T.%NZ",
time_zone => "UTC"
);
my $dt = $p->parse_datetime($s);
$dt->set_time_zone("Europe/Berlin");
say join ' ', $dt->ymd, $dt->hms; # shows 2016-12-22 07:16:29
The Algorithm
If you want to change a time value from one timezone to another timezone, you must be able to indicate both timezones.
After all, if you set if you want to convert "12:30" to GMT or US/Eastern or Venezuelan time, which means adding/subtracting some amount of hours or hours and minutes, you need to know what timezone is the starting time zone, otherwise, the calculation won't know how much to add or subtract.
If you use DateTime->now;, the timezone is defaulted to the system-time, which may not be the timezone you want to convert from.
In the below code, I demonstrate how to initialize the datetime object to the right starting timezone (fromtimezone) and how to convert that time to the ending timezone (totimezone)...
Working Code
I could not find a Perl sandbox online with the DateTime CPAN module installed.
use strict;
use DateTime;
sub convertTimeZonesForTime {
my ($args) = #_;
my $time = $args->{time};
my $date = $args->{date};
my $totimezone = $args->{totimezone};
my $fromtimezone = $args->{fromtimezone};
my $format = $args->{format} || '%H:%M:%S';
my ($year, $month, $day) = map {int $_} split('-', $date);
my ($hour, $minute, $second) = map {int $_} split(':', $time);
$year ||= 1999 if !defined $year;
$month ||= 1 if !defined $month;
$day ||= 1 if !defined $day;
$hour ||= 12 if !defined $hour;
$minute ||= 30 if !defined $minute;
$second ||= 0 if !defined $second;
my $dt = DateTime->new(
year=>$year,
month=>$month,
day=>$day,
hour=>$hour,
minute=>$minute,
second=>$second,
time_zone => $fromtimezone,
);
my $formatter = new DateTime::Format::Strptime(pattern => $format);
$dt->set_formatter($formatter);
$dt->set_time_zone($totimezone);
return "$dt";
}
print(convertTimeZonesForTime({
'totimezone'=>'America/Denver',
'fromtimezone'=>'US/Eastern',
'time'=>'12:30:00',
}));
Output:
10:30:00