Get last day of month in Template Toolkit / Date::Manip - perl

I want to offer promotions on my site that always begin and end on the first and last days of the current month.
Getting the first day of the month is trivial (it's always the first), but I'd like to also do the same for the last day of the month.
In the docs it mentions that you can use either Date::Manip or Date::Calc , but based on those documentations I'm not clear on the best way to accomplish this.
What's the best way to show the last day of the month in Template Toolkit?

The way I got this working was basically to load the Date::Calc module through the template toolkit plugin. Then I set "last_day" to the number of days in the month.
The Days_in_Month call requires the date and month (to handle leap years), so I pass the result of date format.
This is the doc containing the format for dates, which is where I got %m.
[%
calc = date.calc;
last_day = calc.Days_in_Month(date.format(date.now(), "%Y"), date.format(date.now(), "%m"));
%]
So to show a range of Month/Day that begins and ends within the current month, I do:
[% date.format(date.now(), "%m/01") %] - [% date.format(date.now(), "%m/") %][% last_day %]
... since the last day of the month will always be double digits, there's no need to pad it with zeros.
Make sure you install the Date::Calc module. If you have it at all, Template Toolkit will load it.

Related

How to print previous month in PowerShell

I want to display only previous month not with the days and year using PowerShell. I can get the desired result using "(Get-Date).AddMonths(-1)" But this command giving me the complete date.
You can use:
(Get-Date).AddMonths(-1).Month
Which gets you the month number, which, for example, would be 10 for October, if it were currently November.
If you want the month name, you can use:
[CultureInfo]::CurrentCulture.DateTimeFormat.GetMonthName((Get-Date).AddMonths(-1).Month)
Which, for month 10, would give:
October
You were pretty close with what you had! Just need one more parameter:
(Get-Date).AddMonths(-1).Month;
In this case we get a return of 10.
You don't say if you want the previous month number, name or short name, so here they each are:
(Get-Date).AddMonths(-1).Month
(Get-Culture).DateTimeFormat.GetMonthName((Get-Date).AddMonths(-1).Month)
(Get-Culture).DateTimeFormat.GetAbbreviatedMonthName((Get-Date).AddMonths(-1).Month)

Why does strptime from Time::Piece not parse my format?

My collegue (who has left the company) has written a bunch of scripts, including batch and Perl scripts, and I'm getting rid of the regional settings dependencies.
In the last Perl script, he's written the following piece of code:
my $format = "%d.%m.%Y %H:%M";
my $today_converted = Time::Piece->strptime($today, $format) - ONE_HOUR - ONE_HOUR - ONE_HOUR - ONE_HOUR - ONE_HOUR;
(the idea is to get five hours before midnight of that particular date)
The value of $today seems to be "03/04/2017" (which stands for the third of April (European dateformat)), which seems not to be understood by Time::Piece implementation:
Error parsing time at C:/Perl64/lib/Time/Piece.pm line 481.
Which format can I use which is understood by Time::Piece Perl implementation?
In the format you have dots . as the date delimiter, but in the data you have slashes /. That's why it doesn't parse. It needs an exact match.
I think it's worth clarifying that strptime() will parse most date and time formats - that's the point of the method. But you need to define the format of the date string that you are parsing. That's what the second parameter to strptime() (in this case, your $format variable) is for.
The letters used in the format are taken from a standard list of definitions which used by every implementation of strptime() (and its inverse, strftime()). See man strptime on your system for a complete list of the available options.
In your case, the format is %d.%m.%Y %H:%M - which means that it will parse timestamps which have the day, month and year separated by dots, followed by a space and the hours and minutes separated by a colon. If you want to parse timestamps in a different format, then you will need to change the definition of $format.

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).

PigLatin-Finding MonthEnd date for a given date

In Pig Latin, is there a built-in function to find the Month End date for a given date ? For example, if the given date is '2015-03-15', the month end date returned should be '2015-03-31' and if given date is '2015-04-15', the month end date should be '2015-04-30'.
This is how you do it:
REGISTER /usr/lib/pig/piggybank.jar;
DEFINE ISOToMonth org.apache.pig.piggybank.evaluation.datetime.truncate.ISOToMonth();
%declare END_OF_MONTH SubtractDuration(AddDuration(ToDate(ISOToMonth('2015-03-15')),'P1M'),'P1D')
A = LOAD 'DummyFileWithOneRow.txt' USING PigStorage(',') AS (f1:chararray, f2:chararray);
result = FOREACH A GENERATE
f1 AS f1,
$END_OF_MONTH AS end_of_month;
DUMP result
The result of this run is:
(1,2015-03-31T00:00:00.000Z).
You can now convert this result to your desired format.
You can do this calculation as part of the foreach on the loaded values.
The ordinary way to do such things, if you do not find that the language in question already has a built-in set of functions to "do such things," is to ... in this case:
Determine the first day of the current month. ("Month/01/Year" This is the only step that you "do by hand.")
Add "one month" to that. (There should be some kind of "DateAdd()" function in your language...)
Finally, using the same function, "subtract one day."
December 15th => December 1st => January 1st (of next year) => December 31st (of this year).
But first, look carefully. "Accountants want to do this sort of thing all the time." There is usually a pretty-good, sometimes very-good, set of functions to do date-manipulation. (And if they're not built-in to the language, there's often a contributed library of "goodies" that someone else already wrote and perfected.)

Template Toolkit display results once foreach loop

I am currently using Template Toolkit and have never learn or use before TT.
For example, I have 10 files, 5 files dated year dd/mm/2011 and 5 files dated dd/mm/2012. I need to display the year once only. I tried using foreach loop but instead of displaying 2011 5 times and 2012 5 times, I want it to display only 1 time.
What I need to achieve is to get the year and using that to create a link to display those documents on that year.
Hope you guys understand and some kind souls please help me out. =x
You'd use a similar approach in TT that you'd use in any other programming language. Make a note of the last year you saw and only print the current one if it's different.
Here's a simple example that you can run with tpage.
$ cat years.tt
[%- dates = [ '01/11/2012', '01/12/2012', '01/01/2013', '01/02/2013'];
lastyear = '';
FOREACH date IN dates;
bits = date.split('/');
IF bits.2 != lastyear;
bits.2 _ "\n";
END;
bits.0 _ '/' _ bits.1 _ "\n";
lastyear = bits.2;
END -%]
$ tpage years.tt
2012
01/11
01/12
2013
01/01
01/02
But you almost certainly want to think about passing a more sensible data structure into TT.