Date::Calc - format the day and month - perl

All I am trying to do here is if the day or month is a single digit, to add a zero in
the front of it. Right now it prints out the date as 201188, and I am looking for
20110808.
#!/usr/bin/perl
use Date::Calc qw(Add_Delta_Days);
my (undef, undef, undef, $day, $month, $year) = localtime();
$year +=1900;
$month +=1;
($year, $month, $day ) = Add_Delta_Days($year, $month, $day, -3)
if ($month =~ /\d{1}/){
s/$month/0$month/
}
if ($day =~/\d{1}/){
s/$day/0$day/
}
print $year,$month,$day;

If you're happy to use Date::Calc, why not use DateTime ?
use DateTime;
my $date = DateTime->now;
$date->subtract(days => 3);
print $date->ymd;
In fact you can reduce that to:
print DateTime->now->subtract(days => 3)->ymd

Use printf instead:
printf "%d-%02d-%02d", $year, $month, $day;
Gives output such as:
C:\perl>perl -we "printf qq(%d-%02d-%02d), 2011,5,4"
2011-05-04
C:\perl>perl -we "printf qq(%d-%02d-%02d), 2011,5,12"
2011-05-12
C:\perl>perl -we "printf qq(%d-%02d-%02d), 2011,22,12"
2011-22-12

if ($month < 10)
{
$month="0$month";
}
if ($day < 10)
{
$day="0$day";
}

Related

Perl Date Comparison Query

I'm trying to output "not ok" if the date provided within an input file is greater than one day from "today" using Perl version 5.8.8.
Initializing with "./code.sh < test.txt" works fine, when test.txt contains the following data:
07/02/2020 08/02/2020
When I rehash the code below to try an use "today's date" as a variable, and only have one date within the input file I get the following error:
Use of uninitialized value in concatenation (.) or string at code.sh line 27, <> line 1
Working code (with two dates in the input file):
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
#my $date = localtime->strftime('%d/%m/%Y');
#print "$date";
my $format = '%d/%m/%Y';
while (<>) {
chomp;
my ($str1, $str2) = split;
# my ($date, $str2) = split;
# my $dt1 = Time::Piece->strptime($date, $format);
my $dt1 = Time::Piece->strptime($str1, $format);
my $dt2 = Time::Piece->strptime($str2, $format);
# print "$date / $str2 ";
print "$str1 / $str2 ";
if ($dt2->julian_day - $dt1->julian_day ==1) {
print "ok\n";
} else {
print "not ok\n";
}
}
Broken code (with one date within the input file):
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
my $date = localtime->strftime('%d/%m/%Y');
print "$date";
my $format = '%d/%m/%Y';
while (<>) {
chomp;
# my ($str1, $str2) = split;
my ($date, $str2) = split;
my $dt1 = Time::Piece->strptime($date, $format);
# my $dt1 = Time::Piece->strptime($str1, $format);
my $dt2 = Time::Piece->strptime($str2, $format);
print "$date / $str2 ";
# print "$str1 / $str2 ";
if ($dt2->julian_day - $dt1->julian_day ==1) {
print "ok\n";
} else {
print "not ok\n";
}
}
Not quite sure what I'm doing wrong...
Any help is appreciated
Please pay more attention when you type your code, your sample had a few miss-types
#!/usr/bin/perl
#
# vim: ai:ts=4:sw=4
#
use strict;
use warnings;
use feature 'say';
use Time::Piece;
my $format = '%d/%m/%Y';
my $date = localtime->strftime($format);
say "Today is: $date\n";
my #str_dates = <DATA>;
chomp(#str_dates);
my $date1 = Time::Piece->strptime($str_dates[0], $format);
my $date2 = Time::Piece->strptime($str_dates[1], $format);
my $days_diff = $date2->julian_day - $date1->julian_day;
my $msg = ($days_diff == 1) ? "ok" :"not ok";
say "$date2 :: $date1 => $msg";
say "$date2 :: $date1 = $days_diff day(s) apart";
__DATA__
07/02/2020
08/02/2020
Output
Today is: 07/02/2020
Sat Feb 8 00:00:00 2020 :: Fri Feb 7 00:00:00 2020 => ok
Sat Feb 8 00:00:00 2020 :: Fri Feb 7 00:00:00 2020 = 1 day(s) apart
NOTE: I would recommend if you use:
Windows OS
notepad++
Linux OS vim
vim better use with options: syntax on, ai,ts=4,sw=4

perl date fetch script assistance

I was just having a go at perl. I was trying to extract the date and time from a line in a text file that begins with
Date: 05/Feb/2017 21:30:00 PST - 06/Feb/2017 06:00:00 PST
I have managed to scavenge a script but Im trying to modify it so it extracts the above to
start date - 2017-02-05 21:30:00
end date - 2017-02-06 06:00:00
any help would be appreciated
#Is it a reg date
} elsif (!$start && $line[$i] =~ /^Date: (.+?) - (.+)$/i) {
$regstartdate = $1;
$regenddate = $2;
} elsif (!$start && $line[$i] =~ /^Date: (.+)$/i) {
#Monday 3rd July 2006
#Friday 30th June 2006 01:00 Hrs EST
$regstartdate = $1;
eval{
$start = &dateconv($regstartdate);
$end = $start;
1;
}
or do{
warn "Could not process start date: $regstartdate";
};
} elsif (!$start && $line[$i] =~ /^Time:\s*(\d+:\d+)[\s\-]+\s+(\d+:\d+)\s+[hH][rR][sS]\s+(\w+)$/i) {
$tz = $3;
$twestartdate = $regstartdate . " ".$1." Hrs ".$3;
$tweenddate = $regenddate . " ".$2." Hrs ".$3;
$start = &dateconv($regstartdate);
$end = &dateconv($regenddate);
} elsif (!$start && $line[$i] =~ /^Time:\s*(\d+:\d+)[\s*\-]+\s*(\d+:\d+)\s+(\w+)$/i) {
$tz = $3;
$regstartdate = $regstartdate . " ".$1." Hrs ".$3;
$regenddate = $regenddate . " ".$2." Hrs ".$3;
$start = &dateconv($regstartdate);
$end = &dateconv($regenddate);
#Is it a reg Time
} elsif (!$start && $line[$i] =~ /^Interruption Time: (\d+:\d+)[\s\-]+(\d+:\d+) (\w+)/i) {
$regstartdate = $regstartdate . " " . $1 . " Hrs " . $3;
$regenddate = $regenddate . " " . $2 . " Hrs " . $3;
$start = &dateconv($regstartdate);
$end = &dateconv($regenddate);
#Is is the start time ?
} elsif (!$start && $line[$i] =~ /^Duration:\s*START DATE (.*)/i) {
$start = &dateconv($1);
#Is it the end time ?
} elsif (!$end && $line[$i] =~ /^END DATE (.*)/i) {
my $endtime = $1;
$end = &dateconv($endtime);
$endtime =~ m/(\w{1,2}ST)/g;
$tz = $1;
Offering a solution using Time::Piece which I prefer - both because I like the interface, but also because it's core as of perl 5.9.5
#!/usr/bin/env perl
use strict;
use warnings;
use Time::Piece;
my $input_format = '%d/%b/%Y %H:%M:%S';
my $output_format = '%Y-%m-%d %H:%M:%S';
while (<DATA>) {
if ( my ( $start_str, $end_str ) = m/Date: (.*) PST - (.*) PST/ ) {
my $start = Time::Piece->strptime( $start_str, $input_format );
my $end = Time::Piece->strptime( $end_str, $input_format );
print "Start:\t", $start->strftime($output_format), "\n";
print "End: \t", $end ->strftime($output_format), "\n";
}
}
__DATA__
Date: 05/Feb/2017 21:30:00 PST - 06/Feb/2017 06:00:00 PST
The reason I like it is because the $start and $end in the above, are 'time objects' so you can do things like:
print $start -> epoch;
print "Elapsed time: ", $end - $start, "s\n";
If you use the DateTime module, parsing and formatting those date strings is trivial:
use strict;
use warnings;
use 5.010;
use DateTime;
use DateTime::Format::Strptime;
my $fmt = DateTime::Format::Strptime->new(pattern => '%d/%b/%Y %H:%M:%S');
my $line = 'Date: 05/Feb/2017 21:30:00 PST - 06/Feb/2017 06:00:00 PST';
$line =~ s/^Date: //;
my #dates = split(/\s*-\s*/, $line);
for my $date (#dates) {
my $dt = $fmt->parse_datetime($date);
say $dt->ymd . ' ' . $dt->hms;
}
Produces:
2017-02-05 21:30:00
2017-02-06 06:00:00
You can adjust the formatting as you see fit.

Quickly getting to local time YYYY-mm-dd HH:MM:SS in Perl?

i want to get local time and formatted as YYYY-mm-dd HH:MM:SS (say 2009-11-29 14:28:29).,
How can i get date in this format YYYY-mm-dd HH:MM:SS ?
i have try
my $format = "%4u-%02u-%02u %02u:%02u:%02u";
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
printf "$format\n", $year+1900, $mon+1, $mday, $hour, $min, $sec;
the print output is that i want ,but how to designed the output to a variable ??
Use sprintf instead of printf.
my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
my $formatted = sprintf "%4u-%02u-%02u %02u:%02u:%02u",
$year+1900, $mon+1, $mday, $hour, $min, $sec;
But it's much simpler to use strftime.
use POSIX qw( strftime );
my $formatted = strftime("%Y-%m-%d %H:%M:%S", localtime);

Issue with Perl File::stat output, need to show date

I am having an issue with getting File::stat to output the last modified date of the file. This is my code so far:
#!/usr/bin/perl
use Time::localtime;
use File::stat;
use warnings;
use File::Find;
my $dirloc = 'E:\tmp\testdir';
sub find_txt {
my $F = $File::Find::name;
if ( ! -d $F && $F =~ /.tar|.exe|.zip/ ) {
my #result = $F;
foreach my $result (#result){
my $timestamp;
$timestamp = (stat("$result"))->[9] or die "No $_: $!";
print "$result : $timestamp\n";
}
}
}
find({wanted => \&find_txt}, $dirloc);
It is outputing something like this:
C:/tmp/testdir/foo/bar/test.tar : 1415305933
I need it to output instead (date format doesn't have to be what is listed, i just want to see the date):
C:/tmp/testdir/foo/bar/test.tar : 11/07/2014
I know that the output it is giving me is the time since epoch but I thought stat was supposed to give the date. Am I doing something wrong? Thanks!
edit: I have tried localtime, and i get: Time::tm=ARRAY(0x245b220), not sure what is happening there
You can use the localtime (Note: not Time::localtime) function to convert the timestamp into something useful
my $date = localtime $timestamp
which will make it a human readable string like Fri Nov 7 15:33:00 2014
Or you can use it in a list context to spit it into individual fields:
my($sec, $min, $hour, $day, $month, $year, $weekday, $yearOfDay, $isDST) = localtime $timestamp

parse timestamp with millisecond in Perl

Assuming I have a bunch of timestamps like "11/05/2010 16:27:26.003", how do parse them with millisecond in Perl.
Essentially, I would like to compare the timestamp to see if they are before or after a specific time.
I tried using Time::Local, but it seems that Time::Local is only capable to parse up second. And Time::HiRes, on the other hand, isn't really made for parsing text.
Thanks,
Derek
use DateTime::Format::Strptime;
my $Strp = new DateTime::Format::Strptime(
pattern => '%m/%d/%Y %H:%M:%S.%3N',
time_zone => '-0800',
);
my $now = DateTime->now;
my $dt = $Strp->parse_datetime('11/05/2010 23:16:42.003');
my $delta = $now - $dt;
print DateTime->compare( $now, $dt );
print $delta->millisecond;
You can use Time::Local and just add the .003 to it:
#!/usr/bin/perl
use strict;
use warnings;
use Time::Local;
my $timestring = "11/05/2010 16:27:26.003";
my ($mon, $d, $y, $h, $min, $s, $fraction) =
$timestring =~ m{(..)/(..)/(....) (..):(..):(..)([.]...)};
$y -= 1900;
$mon--;
my $seconds = timelocal($s, $min, $h, $d, $mon, $y) + $fraction;
print "seconds: $seconds\n";
print "milliseconds: ", $seconds * 1_000, "\n";