how many days have passed since Friday - Perl Variable - perl

I'm trying to calculate the number of days that have passed since last Friday?
For example, today is 7/19/2022, and last Friday was 7/15/2022 therefore, four days have passed.
7/19/2022 - 7/15/2022 = 4 days
I need this to update every day to just display # of days.
Can someone help me write this out to assign to a variable?
Thank you in advance!!! (new to coding)

You can use localtime and simple modular arithmetic:
( (localtime)[6] - 5 ) % 7
( (current day index) - (friday day index) ) mod (days in a week)

You can use Date::Calc Module. Here is the one liner version.
perl -E 'use Date::Calc qw(:all); say Delta_Days(2022,7,15, 2022,7,19,)'

Related

Finding Palm Sunday

Palm Sunday is the Sunday before Easter Sunday. Finding Easter Sunday can be achieved with:
use Time::Moment;
use Time::Moment::Adjusters qw(WesternEasterSunday PreviousDayOfWeek);
# 2018-04-01T00:00:00Z
my $easter_sunday = Time::Moment->new(year => 2018)->with(WesternEasterSunday);
Finding the Sunday before that could be achieved with Time::Moment::Adjusters' PreviousDayOfWeek(7):
$adjuster = PreviousDayOfWeek($day);
The $adjuster adjusts the date to the previous occurrence of the given day of the week [1=Monday, 7=Sunday] that is before the date.
But if I apply this adjuster, I get a Tuesday five days earlier!
# 2018-03-27T00:00:00Z
my $palm_sunday = $easter_sunday->with(PreviousDayOfWeek(7))
Since Palm Sunday is always seven days prior to Easter Sunday, I could achieve this with Time::Moment's minus_days(7), but since I want to find a number of other holidays that are much simpler to find using Time::Moment::Adjusters, I would really like to find the root of this unexpected behavior.
Thank you Simon for the report and the PR and thank you #simbabque for the test! I have shipped v0.44 to CPAN. You are excellent citizens in the opensource community!
--
chansen

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.

Perl workweek conversion is incorrect

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.

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

How can I get start of month in epoch form from random epoch timestamp in Perl?

I get some times from a database and I am trying to store them by month, using the epoch form.
So I could have some random times like:
1354120744
1328978360
1297388332
and for each one I want to find the epoch value which represents the 1st of that month
so for the last timestamp it would be:
1296518400 (using lovely epochconverter.com).
I know that I can use POSIX mktime to reduce the timestamp down to days, mins etc and change them accordingly etc as was the answer to a post I did a while ago: How to go back months in Perl taking account of different days in month?
The trouble I have with that is that while I can zero times, I'm worried that by changing the date the day of week will not match up, so essentially making an invalid date. This may be an unnecessary worry; I don't know if it would make a difference having the wrong day of week if the times are validated.
I couldn't see any other POSIX methods which seemed useful. Any help appreciated!
I stopped worrying about timestamp issues since I've met DateTime:
$ perl -MDateTime -E 'say DateTime->from_epoch(epoch => 1354120744)->truncate(to => "month")->epoch;'
1351728000
My first thought would be to use Time::Local to convert the localtime results back to epoch, with the appropriate values forced to 0 or 1 as needed. Note that day of week is not among the input values it expects, so you don't need to worry about what happens if you get that wrong.
$start_of_month_epoch = timelocal(0, 0, 0, 1, $month, $year);
The trouble I have with that is that while I can zero times, I'm worried that by changing the date the day of week will not match up, so essentially making an invalid date.
mktime(3) ignores the wday, yday and isdst fields for this exact reason. You can safely adjust the mday to 1 then call POSIX::mktime() again to turn it back to an epoch value.
my #t = localtime();
$t[0] = $t[1] = $t[2] = 0; # sec/min/hour
$t[3] = 1; # mday
my $epoch_start_of_month = mktime #t;
Or simpler
my $epoch = mktime 0, 0, 0, 1, (localtime)[4,5];