How can I convert dates to required format in Perl? - perl

I have current date as 1/10/2010 I need to convert it into 1 October 2010. Is there any module to convert?

Use DateTime::Format::Strptime.
use DateTime::Format::Strptime;
my $Strp = DateTime::Format::Strptime->new(
pattern => '%d/%m/%Y',
time_zone => 'UTC',
);
my $dt = $Strp->parse_datetime('1/10/2010');
print $dt->strftime('%d %b %Y');
Edit: Thanks to #davorg for a hint with new.

You can try:
my $date = '1/10/2010';
my #abbr = qw( dummy Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
my($d,$m,$y) = split/\//g,$date;
my $new_date = $d.' '.$abbr[$m].' '.$y;

Related

Time interval between two dates with Perl

I'm adding two dates and trying to calculate the time, but I'm getting the following error:
Error parsing time at /usr/local/lib/x86_64-linux-gnu/perl/5.30.0/Time/Piece.pm line 598.
I install Time::Piece with cpan: cpan Time::Piece.
This my code:
our #months = qw( 01 02 03 04 05 06 07 08 09 10 11 12 );
our #days = qw(Domingo Segunda Treça Quarta Quinta Sexta Sabado Domingo);
($sec,$min,$hour,$mday,$mon,$year,$wday,$day,$isdst) = localtime();
our $ano = "2021";
our $day = "$mday";
our $mes = $months[$mon];
our $data = $mes."-".$day."-".$ano;
our $horario = $hour.":".$min.":".$sec;
our $horario2 = $hour.":".$min.":".$sec;
our $data1 = $ano."-".$mes."-".$day;
our $data2 = $day."/".$mes."/".$ano;
our $str1 = 'Execution completed at '.$data2.' '.$horario.' AM';
our #mes = qw( Jan Feb Mar APr May Jun Jul Agu Sep Oct Nov Dec );
our #days = qw(Domingo Segunda Treça Quarta Quinta Sexta Sabado Domingo);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
$nomeMes = $mes[$mon];
our #mes = qw( Jan Feb Mar APr May Jun Jul Agu Sep Oct Nov Dec );
our #days = qw(Domingo Segunda Treça Quarta Quinta Sexta Sabado Domingo);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
our $data2 = $day."/".$mes."/".$ano;
our $horario = $hour.":".$min.":".$sec;
my $str2 = 'Execution completed at '.$data2.' '.$horario.' AM';
my #times = map Time::Piece->strptime(/(\d.+M)/, '%m/%d/%Y %H:%M:%S %p'), $str1, $str2;
my $delta = $times[1] - $times[0];
$tempo = $delta->pretty;
What am I doing wrong? What can I do to make this function work?
The matched pattern of $str1 is 20/12/2021 13:58:3 AM
Problems:
There's no 20th month
There's no 13 AM
Can give the wrong answer near a switch from Daylight-Saving Time.
Also, there's a couple of problems strptime ignores:
You should be using %I instead of %H for 12-hour time.
There's a lack of leading zeros where they are normally expected (minutes and seconds).
You appear to be asking the following:
Given the year, month, day, hour, minute and second components of a local time, how do I obtain the corresponding epoch time so I can perform a difference?
To achieve this, use Time::Local's timelocal*.
use Time::Local qw( timelocal_posix );
my $time = timelocal_posix( $sec, $min, $hour, $day, $month - 1, $year - 1900 );
You could also use DateTime. This more powerful module can give you differences in amounts other than seconds.
Either way, you will still have problems near a switch from DST. There's simply not enough information to address that. That's the problem with dealing with local times with no offset.
I use the script:
our $str2 = $ano.'/'.$mes.'/'.$day.' '.$hour.':'.$min.':'.$sec.'.267-05:00';
my #times = map Time::Piece->strptime( s/\..*//r, '%Y/%m/%d %H:%M:%S'), $str1, $str2;
our $delta = $times[1] - $times[0];
print $delta->pretty;
It's work.
Thanks very much Ikegami for help.

perl to open file with yesterday's date in localtime()

i need to open files with todays date and yesterdays date i can open todays file ok but am don't know how to open yesterdays, i am using localtime because my perl verson is 5.8.8.
so the other time/date modules are not available
this is what i have so far
#!/usr/local/bin/perl
#months = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
#days = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
$year = $year+1900;
print "c:\\DBR_$year\\$months[$mon]\\Failures_output\\$mday$months[$mon]report.csv"
|| die "can't open output file for reading: $!";
this prints
c:\DBR_2014\May\Failures_output\5Mayreport.csv
now how do i open same files with yesterdays date
A localtime/mktime roundtrip will give you the epoch number for midnight at the start of yesterday (i.e. the time where mday is 1 less than now)
use POSIX 'mktime';
my #now = localtime();
my $yesterday = mktime 0, 0, 0, $now[3]-1, $now[4], $now[5];
You can then put this into strftime to give you the time string; you don't need to have an array of months like that
use POSIX 'strftime';
my $path = strftime("c:\\DBR_%Y\\%b\\Failures_output\\%d%breport.csv", localtime($yesterday));
(You don't have to worry about the case where mday is already 1 because mktime will handle that properly).
localtime can take an epoch seconds argument, so do get yesterday's date, just call
#yesterday = localtime( time - 86400 ); # 86400 = 24 * 60 * 60

perl print current year in 4 digit format

how do i get the current year in 4 digit this is what i have tried
#!/usr/local/bin/perl
#months = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
#days = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
$year = $year+1900;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
print "DBR_ $year\\$months[$mon]\\Failures_input\\Failures$mday$months[$mon].csv \n";
This prints DBR_ 114\Apr\Failures_input\Failures27Apr.csv
How do I get 2014?
I am using version 5.8.8 build 820.
use Time::Piece;
my $t = Time::Piece->new();
print $t->year;
Move the line:
$year = $year+1900;
To after that call to localtime() and to become:
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
$year = $year+1900;
The best way is to use the core library Time::Piece. It overrides localtime so that the result in scalar context is a Time::Piece object, you can use the many methods that the module supplies on it. (localtime in list context, as you have used it in your own code, continues to provide the same nine-element list.)
The strftime method allows you to format a date/time as you wish.
This very brief program produces the file path that I think you want (I doubt if there should be a space after DBR_?) Note that there is no need to double up backslashes inside a single-quoted string unless it is the last character of the string.
use strict
use warnings;
use Time::Piece;
my $path = localtime->strftime('DBR_%Y\%b\Failures_input\Failures%m%d.csv');
print $path;
output
DBR_2014\Apr\Failures_input\Failures27Apr.csv
One option to get the 4 digit year:
#!/usr/bin/perl
use POSIX qw(strftime);
$year = strftime "%Y", localtime;
printf("year %02d", $year);
You can also use
my ($y,$m,$d) = Date::Calc::Today();
$y variable will contain 2019
$m variable will contain 8
$d variable will contain 9
at the time of writing this answer ( 9th August 2019 )
The simplest way, I find, to get the year is:
my $this_year = (localtime)[5] + 1900;

How can I convert of the unix date output across multiple time zones to UTC, in Perl?

In Perl, how would one efficiently parse the output of unix's date command, taking into account time zone, and also convert to UTC?
I've read many similar questions on stackoverflow, but few seem to take into account parsing multiple time zones. Instead they seem to set the timezone manually and assume it to stay fixed.
# Example Input Strings:
my #inputs = (
'Tue Oct 12 06:31:48 EDT 2010',
'Tue Oct 12 07:49:54 BST 2010',
);
I tried the following to no avail:
foreach my $input ( #inputs ) {
my $t = Time::Piece->strptime( $input,
'%a %b %d %T %Z %Y' );
print $t->cdate, "\n";
}
It seems the problem is the time zone (%Z). Additionally, a time zone field does not seem to exist in Time::Piece, which would require me to write custom code to convert to UTC, which just seems... wrong.
Context:
I'm attempting to parse legacy logs from a variety of sources that use the unix date command for timestamps. Ideally, I'd like to convert all timestamps to UTC.
Any help would be greatly appreciated.
If you know how to disambiguate the TZs, just pop them into a dispatch table:
use strict; use warnings;
use DateTime::Format::Strptime ();
my #inputs = (
'Tue Oct 12 06:31:48 EDT 2010',
'Tue Oct 12 07:49:54 BST 2010',
);
my %tz_dispatch = (
EDT => build_parser( 'EST5EDT' ),
BST => build_parser( '+0100' ),
# ... etc
default => build_parser( ),
);
for my $input (#inputs) {
my ($parser, $date) = parse_tz( $input, %tz_dispatch );
print $parser->parse_datetime( $date ), "\n";
}
sub build_parser {
my ($tz) = #_;
my %conf = (
pattern => '%a %b %d %T %Z %Y',
on_error => 'croak',
);
#conf{qw/time_zone pattern/} = ($tz, '%a %b %d %T %Y')
if $tz;
return DateTime::Format::Strptime->new( %conf );
}
sub parse_tz {
my ($date, %tz_dispatch) = #_;
my (#date) = split /\s/, $date;
my $parser = $tz_dispatch{splice #date, 4, 1};
return $parser
? ($parser, join ' ', #date)
: ($tz_dispatch{default}, $date);
}
The Perl DateTime FAQ on timezones has a good background on why EDT and EST cannot be used in most conversions. The issue is that other countries also have an Eastern time zone with the same 3 letter abbreviation. EST EDT is ambiguous without other clues.
You might look at other modules, or just assume that "EDT" is the same as "EST5EDT" if that is true.
If you are using Date::Time::Strptime, you can use %O for the Olson Time Zone name and do a manual fixup before parsing.
i.e. if you know that EDT in your input means America/New_York, do this:
$time_in =~ s{EDT}{America/New_York};
and instead of
%a %b %d %T %Z %Y
for your time zone spec use
%a %b %d %T %O %Y
I've always found Date::Manip::ParseDate to be good for these sorts of situations.
use strict;
use warnings qw<FATAL all>;
use Date::Manip qw<ParseDate UnixDate>;
my #inputs = (
q<Tue Oct 12 06:31:48 EDT 2010>,
q<Tue Oct 12 07:49:54 BST 2010>,
);
sub date2epoch($) {
my $user_string = shift();
my $timestamp = ParseDate($user_string);
my $seconds = UnixDate($timestamp, "%s");
return $seconds;
}
sub epoch2utc($) {
my $seconds = shift();
return gmtime($seconds) . q< UTC>;
}
for my $random_date (#inputs) {
my $epoch_seconds = date2epoch($random_date);
my $normal_date = epoch2utc($epoch_seconds);
print "$random_date == $normal_date\n";
}
When run, that produces this:
Tue Oct 12 06:31:48 EDT 2010 == Tue Oct 12 10:31:48 2010 UTC
Tue Oct 12 07:49:54 BST 2010 == Tue Oct 12 06:49:54 2010 UTC
which seem to be what you're looking for.
I'm a little late on this, but GNU date itself is good at parsing dates:
$ date -u -d 'Thu Oct 14 01:17:00 EDT 2010'
Thu Oct 14 05:17:00 UTC 2010
I don't know how it resolves the EDT ambiguity though.
I agree with Jander on date command. -d and -u are great and save a lot of code lines.

How do you read the system time and date in Perl?

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