How do I convert local time to a Unix timestamp in Perl? - perl

For example: from date: 10/02/2010
How do I convert an equal timestamp for 10/02/2010 00:00:00 in Perl?
I can't use local time or time .. is there another way to achieve this?

You can use the Time::Local core module:
use Time::Local 'timelocal';
my ($d, $m, $y) = split '/', '10/02/2010';
my $time = timelocal(0, 0, 0, $d, $m-1, $y);
Note that the month argument for timelocal() is in the range 0..11.

Without localtime():
use Time::Local;
$time = timelocal($sec, $min, $hour, $mday, $mon, $year);
(See perldoc.)
A standard way would be something like:
use POSIX;
use strict;
use warnings;
my $sec = 0;
my $min = 0;
my $hour = 0;
my $day = 10;
my $mon = 2 - 1;
my $year = 2010 - 1900;
my $wday = 0;
my $yday = 0;
my $unixtime = mktime ($sec, $min, $hour, $day, $mon, $year, $wday, $yday);
print "$unixtime\n";
my $readable_time = localtime($unixtime);
print "$readable_time\n"
(From Converting Unix time and readable time with Perl)

You could use Date::Parse:
use Date::Parse;
print str2time('10/02/2010 00:00:00');
On my machine this prints 1285970400, which corresponds to October 2nd, 2010 (I live in +1 GMT with +1 Wintertime.)

I think you want the built-in module Time::Local.

The DateTime module should be helpful here. In particular, I believe the DateTime::Format::Natural module can parse a user-supplied date string. From there, you have a DateTime object and can print it out or transform it as you like.

Depending on where your initial date is coming from you might be able to parse it using
Date::Manip
and calling
ParseDate("10/02/2010")
You can then take that output and convert it into whatever format you wish.

Related

Perl subtract two dates

I am fairly new in Perl.
I am trying to subtract two dates in this format
15.07.16 23:13:34
15.07.16 20:04:24
I know that I have to convert this string in a date object. My problem is I am restricted to the basic perl without installing extra packages. Is there a way to do it?
My Version is v5.8.4 and the output should be 03:09:10.
You say that you're using Perl 5.8.4. You really need to get that updated and get the ability to install CPAN modules.
But, here's a way to do what you want using only core Perl functionality that was available in 5.8.4.
#!/usr/bin/perl
use strict;
use warnings;
use Time::Local;
my $date1 = '15.07.16 23:13:34';
my $date2 = '15.07.16 20:04:24';
my $diff = date2sec($date1) - date2sec($date2);
print secs2duration($diff);
sub date2sec {
my ($date) = #_;
my ($day, $mon, $yr, $hr, $min, $sec) = split(/[. :]/, $date);
# I've assumed that your timestamps are in your local timezone,
# so I've used timelocal() here. If your timestamps are actually
# UTC, you should use timegm() instead.
return timelocal($sec, $min, $hr, $day, $mon-1, 2000 + $yr);
}
sub secs2duration {
my ($secs) = #_;
my $hours = int($secs / (60*60));
$secs %= (60*60);
my $mins = int($secs / 60);
$secs %= 60;
return sprintf '%02d:%02d:%02d', $hours, $mins, $secs;
}

How to convert unix epoch time to readable format in perl

How do I convert 1461241125.31307 in perl. I tried:
use Date::Parse;
$unix_timestamp = '1461241125.31307';
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($unix_timestamp);
$mon += 1;
$year += 1900;
$unix_timestamp_normal = "$year-$mon-$mday $hour:$min:$sec";
result: 2016-4-21 5:18:45 (no padding of hour)
How do I pad it and make it GMT. I want the result to say 2016-04-21 12:18:45
Thanks for the answers folks.
use DateTime;
$unix_timestamp = '1461241125.31307';
my $dt = DateTime->from_epoch(epoch => $unix_timestamp);
print $dt->strftime('%Y-%m-%d %H:%M:%S'),"\n";
Easiest way:
print scalar localtime $unix_timestamp;
Documentation: http://perldoc.perl.org/functions/localtime.html
For GMT, use gmtime:
print scalar gmtime $unix_timestamp;
Documentation: http://perldoc.perl.org/functions/gmtime.html (Basically says: Everything like localtime, but outputs GMT time.)
For custom formats, try DateTime:
use DateTime;
my $dt = DateTime->from_epoch(epoch => $unix_timestamp);
print $dt->strftime('%Y-%s');
See http://search.cpan.org/perldoc?DateTime for all options. Lots of formats could be created even more easily using the predefined DateTime Formatters: http://search.cpan.org/search?query=DateTime%3A%3AFormat&mode=all
use POSIX qw( strftime );
my $epoch_ts = '1461241125.31307';
say strftime('%Y-%m-%d %H:%M:%S', gmtime($epoch_ts));
Use gmtime instead of localtime
perldoc -f gmtime :
gmtime EXPR
gmtime Works just like "localtime" but the returned values are localized
for the standard Greenwich time zone.
Note: When called in list context, $isdst, the last value returned
by gmtime, is always 0. There is no Daylight Saving Time in GMT.
Portability issues: "gmtime" in perlport.

convert date format from 9/15/12 to 255 in perl

I was wondering if someone could show me how to convert 9/15/12 to 255 format.
Something in php from getdate array you can get ydate.
I think you're asking how you can get the 1 <= yday <= 366 day representation of a date, similar to yday in php's getdate(). As is common in PERL, there's more than one way to do it. The simplest mechanism would be to use localtime() for today's date:
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
If you want to do it for a different date, I'd probably use the TimeDate CPAN module
use Date::Parse;
print time2str("%j",str2time("9/15/2012"));
I think Tawnos's mentioning php's yday from getdate() is on target. Here's one option (assuming 2012 is the year in your date string):
use strict;
use warnings;
use Date::Calc qw/Day_of_Year/;
my $date = '9/15/12';
my ( $month, $day, $year ) = split '/', $date;
my $doy = Day_of_Year( "20$year", $month, $day ) - 1;
print $doy; # (0 - 365)
Output:
258
Do you want the day of the year? That would be day 258 (0-based) or the 259th day (1-based), though. Using only core Perl:
use Time::Local qw( timegm );
my $date = '9/15/12';
my ($m,$d,$y) = split(qr{/}, $date);
my $epoch = timegm(0,0,0, $d,$m-1,$y);
my $yday = ( gmtime($epoch) )[7]; # 258 (0-based index)
Note that timegm+gmtime is applicable no matter the time zone of the date.
Here's another way, using the core module Time::Piece :
#!/usr/bin/env perl
use strict;
use warnings;
use Time::Piece;
my $t = Time::Piece->strptime(shift,"%m/%d/%y");
print $t->yday, "\n";
The day output is zero-relative: January 01 = 0.
my $dt = '9/15/2012';
my ( $m, $d, $y ) = split( '/', $dt );
my $t = POSIX::mktime( 0, 0, 0, $d, $m - 1, $y - 1900 );
say [ localtime $t ]->[7] - 3;
Julian date (minus 1) is slot 7 in the list return from localtime and gmtime.
Why subtract 3? I don't know; Sept 15 is 259 Julian. Still it performs the function mapping '9/15/2012' to 255.
You can use only function strftime from core module POSIX.
use strict;
use POSIX qw(strftime);
print strftime "%j", localtime(time);

Convert Old Unix Date to Perl and compare

Requirement - I have file name called "Rajesh.1202242219". Numbers are nothing but a date "date '+%y''%m''%d''%H''%M'" format.
Now I am trying to write a perl script to extract the numbers from file name and compare with current system date and time and based on output of this comparison, print some value using perl.
Approach:
Extract the Digit from File name:
if ($file =~ /Rajesh.(\d+).*/) {
print $1;
}
Convert this time into readable time in perl
my $sec = 0; # Not Feeded
my $min = 19;
my $hour = 22;
my $day = 24;
my $mon = 02 - 1;
my $year = 2012 - 1900;
my $wday = 0; # Not Feeded
my $yday = 0; # Not Feeded
my $unixtime = mktime ($sec, $min, $hour, $day, $mon, $year, $wday, $yday);
print "$unixtime\n";
my $readable_time = localtime($unixtime);
print "$readable_time\n";
find Current time and compare...
my $CurrentTime = time();
my $Todaydate = localtime($startTime);
But the problem here is, I am not getting solution of how to extract 2 digit from $1 and assign to $sec, $min, etc. Any help?
Also, if you have good approach for this problem statement, Please share with me
I like to use time objects to simplify the logic. I use Time::Piece here because it is simple and light weight (and part of the core). DateTime can be another choice.
use Time::Piece;
my ( $datetime ) = $file =~ /(\d+)/;
my $t1 = Time::Piece->strptime( $datetime, '%y%m%d%H%M' );
my $t2 = localtime(); # equivalent to Time::Piece->new
# you can do date comparisons on the object
if ($t1 < $t2) {
# do something
print "[$t1] < [$t2]\n";
}
Might as well teach DateTime::Format::Strptime to make the comparison much simpler:
use DateTime qw();
use DateTime::Format::Strptime qw();
if (
DateTime::Format::Strptime
->new(pattern => '%y%m%d%H%M')
->parse_datetime('Rajesh.1202242219')
< DateTime->now
) {
say 'filename timestamp is earlier than now';
} else {
say 'filename timestamp is later than now';
};
my ($year, $month, $day, $hour, $min) = $file =~ /(\d{2})/g;
if ($min) {
$year += 100; # Assuming 2012 and not 1912
$month--;
# Do stuff
}
I think unpack might be a better fit.
if ( my ( $num ) = $file =~ /Rajesh.(\d+).*/ ) {
my ( $year, $mon, $day, $hour, $min ) = unpack( 'A2 A2 A2 A2 A2', $num );
my $ts = POSIX::mktime( 0, $min, $hour, $day, $mon - 1, $year + 100 );
...
}
Using a module that parses dates might be nice. This code will parse the date and return a DateTime object. Refer to the documentation to see the many ways to manipulate this object.
use DateTime::Format::Strptime;
my $date = "1202242219";
my $dt = get_obj($date);
sub get_obj {
my $date = shift;
my $strp = DateTime::Format::Strptime->new(
pattern => '%y%m%d%H%M'
);
return $strp->parse_datetime($date);
}

Perl - How to convert a date?

How to convert date format YYYY-MM-DDTHH:MM:SSZ to YYYY-MM-DD HH:MM + 8 hours?
For example:
Input: 2011-07-07T18:05:45Z
Output: 2011-07-08 02:05
Let's start with Rahul's snippet, and add in the date math and output formatting...
use DateTime;
use DateTime::Format::ISO8601;
use DateTime::Format::Strptime;
my $string = '2011-07-07T18:05:45Z';
my $dt = DateTime::Format::ISO8601->parse_datetime( $string );
die "Impossible time" unless $dt;
my $formatter = new DateTime::Format::Strptime(pattern => '%Y-%m-%d %T');
$dt->add( hours => 8 )->set_formatter($formatter);
print "$dt\n";
I've added the use of DateTime::Format::Strptime, in order to specify the desired output format.
Then I've added three more lines:
First I create a formatter, and feed it the output pattern I desire.
Next I add eight hours to the original date, and I assign the output
formatter by chaining the set_formatter() call to the add() call.
Then I print it.
Are you using the DateTime modules?
Specifically, here's a link to DateTime::Format::ISO8601 that reads/writes ISO 8601 format you mentioned as your input.
If you don't have DateTime, you surely have Time::Piece:
use strict;
use warnings;
use Time::Piece;
use Time::Seconds qw(ONE_HOUR);
my $str = '2011-07-07T18:05:45Z';
my $t = Time::Piece->strptime($str, "%Y-%m-%dT%TZ");
$t += 8 * ONE_HOUR;
print $t->strftime("%Y-%m-%d %H:%M"),"\n";
Taken From
How can I validate a "yyyy-MM-dd'T'HH:mm:ssZ" date/timestamp in UTC with Perl?
use DateTime;
use DateTime::Format::ISO8601;
my $string = '2010-02-28T15:21:33Z';
my $dt = DateTime::Format::ISO8601->parse_datetime( $string ); die "Impossible time" unless $dt;
It doesn't work, result is 2010-02-28T15:21:33
Then, do it the hard way...
use Time::Local
use warnings;
use strict;
$time = '2010-02-28T15:21:33Z';
my ($year, month, day) = split (/-/, $time)
$year -= 1900; #Year is an offset of 1900
$month -= 1; #Months are 0 - 11
#Now split the time off of the day (DDTHH:MM:SS)
$day = substr($day, 0, 2);
time = substr($day, 3)
#Now split the time
(my $hour, $minute, $second) = split(/:/, $time);
$second =~ s/Z$//; #Remove Z
my $time_converted = timelocal($second, $minute, $hour, $day, $month, $year);
#Now you have the time, Add eight hours
my $hours_in_seconds = 8 * 60 * 60;
$time_converted += $hours_in_seconds;
# Almost done: Convert time back into the correct array:
($second, $minute, $hour, $day, $month, $year) = localtime($time_converted);
$year += 1900;
$month += 1;
# Now, reformat:
my $formatted_time = sprint (%04d-%02d-%02d %02d:%02d),
$year, $month, $day, $hour, $minute;