Perl workweek conversion is incorrect - perl

I'm faced a weird problem.
I have date in form of Tue Feb 25 00:20:13 2014.
my task is to calculate the week number and the week day.
I tried the following
use Time::Piece;
my $date="Tue Feb 25 00:20:13 2014";
my $db_date=Time::Piece->strptime($date, "%a %b %d %H:%M:%S %Y");
my $ww=$db_date->strftime("%W.%w-%Y);
print $ww;
When I run the script I get the output as
08.2-2014
which is wrong, the expected output is
09.2-2014
I want to know where did i go wrong?
pls help...

You're using the "%W" strftime() conversion. Time::Piece doesn't specify the meaning of "%W", but the documentation for the equivalent C function says that "%W" starts counting with the first week that contains a Monday. It sounds like you want the ISO 8601 week number, which starts counting with the first week that contains at least four days, in which case the "%V" conversion should do what you want.

Related

Error when dealing with old and historical dates in Perl Time::Piece

It seems Time:Piece gives me this error:
Error parsing time at /usr/lib/perl5/site_perl/Time/Piece.pm line 481.
after the line where I use strptime with some old dates.
My code contains this:
my $ddate = "$month / $day / $year";
my $tmp = Time::Piece->strptime( $ddate, "%m / %d / %Y");
and $$date takes dates from a database using DBI that contains historical and old dates (dates back to the 10th and 9th centuries AD). How can I deal with this if there is any solution?
You'll have to use something other than Time::Piece if you want to deal with timestamps before 1970.
If you want to use the Gregorian calendar, you can use DateTime.
If you want to use the Julian calendar, you can use DateTime::Calendar::Julian.
The Gregorian calendar was introduced in September, 1582, and it was used universally by 1918. In between, calendar usage varied by country.
$ perl -MDateTime::Calendar::Julian -E'
say
DateTime::Calendar::Julian->new(year => 1013, month => 2, day => 22)
->strftime("%a");
'
Sun
Alternatively, Date::Convert looks promising if you're just care about dates (not timestamps).

18 digit julian timestamp in perl

I need to get 18-digit Julian Timestamp in my perl script. Could anyone help me in this? However I have written a subroutine to achieve this but it does not look good to me since it always gives me a number ending with 6 zeroes. Please help to get a proper 18-digit J-timestamp.
sub GetJulianTimestamp()
{
my $t = `perl -e 'print time, "\n"'`;
return (($t * 1000000 ) + 210866803200000000);
}
Based on the comments, you appear to be asking how to obtain the number of microseconds since the unix epoch.
use Time::HiRes qw( );
my $microsec_time = int( Time::HiRes::time() * 1_000_000 );
return 210866803200000000 + $microsec_time;
I agree with the answer given by ikegami, except the amount to be added to the unix epoch needs to be changed. The value 210866803200000000 corresponds to November 24, 4714 BC, 00:00 Universal Time, Gregorian proleptic calendar. But the epoch of Julian dates is at noon, not midnight. So the amount to be added should be 210,866,760,000,000,000. And of course there is no official name for a Julian date that has been converted to microseconds, so anyone using such a number would have to provide an explanation to anyone who is receiving the data.

Subtracting a Minute in Perl

I have a variable in Perl that I initialized as $invoice_date = '1/6/14' (June 1st 2014). How can I determine the datatype that Perl considers this variable to be?
I'd like to subtract a minute from the invoice date to get May 31 2014 11:59PM. How can I do this with or without declaring $invoice_date to be a certain datatype?
Update: Thanks for the comments and answers. Since it is a string, I am going to try to concatenate the time portion. I have a another variable $period_end_date which is set to May 31, 2014. I'm going to try to concatenate the 11:59PM to it.
The string is subsequently sent in a SQL statement. If I can figure out what SQL expects for the string, it should be possible to insert the time portion.
You need some date manipulation module as '1/6/14' is plain string, and two digit years were abandoned prior to Y2K event.
use Time::Piece;
use Time::Seconds;
my $t = Time::Piece->strptime("1/6/2014", "%d/%m/%Y");
$t -= ONE_MINUTE;
print $t;
output
Sat May 31 23:59:00 2014

Time::Piece is returning a wrong value

I am trying to convert date from yymmdd to YYYY-MM-DD with Time::Piece module. With the input as Nov 31, 2000 (20001131), I am getting output as 2000-12-01. In reality, Nov 31 doesn't even exists.
use Time::Piece;
my $dt_str = Time::Piece->strptime('20001131', '%Y%m%d')->strftime('%Y-%m-%d');
print $dt_str;
Am I missing something here?
Internally, it does only rough validation and error reporting, and then performs the same transformations as POSIX::mktime does; any days beyond the end of a month will just cause it to advance the produced date into the next month. This does seem a little inconsistent; since it allows that for days, I'd also expect it to treat '20005931' as '2004-12-01', but instead it errors out.

Month ago from a date given a date in bash or perl

I will be reading random dates from a files, I want to substract 4 months from that date. I am programming in Perl but I can use a bash command.
If i have the 10/14/2013 i will get 06/14/2013.
Thanks a lot!
Karem
use DateTime::Format::Strptime qw( );
my $format = DateTime::Format::Strptime->new(
pattern => '%m/%d/%Y',
on_error => 'croak',
);
my $dt = $format->parse_datetime('10/14/2013');
$dt->subtract( months => 4 );
say $format->format_datetime($dt);
$ date '+%m/%d/%Y' --date='02/14/2013 4 month ago'
10/14/2012
The CPAN module Date::Manip is perfect for this sort of thing. Date::Manip is quite powerful in that it understands business days and holidays... and can parse arbitrary date strings like "next Tuesday" or "3rd Thursday in August".
You should give it a shot; I bet you'll find it quite useful.
Here's a short example the solves your current problem:
#!/usr/bin/perl
use Date::Manip;
my $d = new Date::Manip::Date("10/18/2013");
print $d->printf("%c"), "\n";
my $delta = new Date::Manip::Delta("4 months ago");
my $od = $d->calc($delta);
print $od->printf("%c"), "\n";
...and this generates the following output:
Fri Oct 18 00:00:00 2013
Tue Jun 18 00:00:00 2013
Beware of months that have more days in them than others!
Here's an example where subtracting one month gives you an answer that you are probably not expecting
endOfMarch=$(date -d "2017-03-31")
today=$endOfMarch
echo $(date -d "$today -1 month" "+%Y-%m-%d")
2017-03-02
Because February only has 28 days, subtracting one month has effectively created the date 2017-02-31 which obviously doesn't exist and so has spilled over the extra days into March given you 2017-03-02
Depending on what you are trying to solve you can reliably calculate n months ago, by creating a date variable set to the first day of the current month, then subtracting the months.
endOfMarch=$(date -d "2017-03-31")
today=$endOfMarch
firstDayOfMonth=$(date -d "$today" "+%Y-%m-01")
echo $(date -d "$firstDayOfMonth -1 month" "+%Y-%m-%d")
2017-02-01
So now you have the correct Month (i.e. February when subtracting 1 month) and you then have to figure out what Day to set the new date to based on your use case.
So adding/subtracting Months is not as straight forward as one might think