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.
Related
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.
I am a Perl newbie and despite that I manage to knock some code together, I am generally slowed down when I need to perform array manipulations -- clearly not yet familiar enough. Currently, I am writing a Perl code that queries a mySQL database and subsequently generates a LaTeX table using the package LaTeX::Table. In the process I need to manipulate arrays, and I am seeking advise to improve my understanding of dealing with arrays in Perl.
In the first part of the code I query a mySQL database using a subroutine:
my #stashYear = queryRecent($Ticker,'YEAR');
print "Last Year:\t";
### Dump the stash contents!
foreach my $array_ref ( #stashYear ) {
print "#$array_ref\n";
}
I have analogue code for a monthly and weekly query. The output looks of the above looks as follows:
bash-3.2$ ./test.pl DG.PA
Last Year: 2015 45.935 62.6 43.4 59.14 256
Last Month: 2016-03 63.9 66.69 62.36 65.47 21
Last Week: 2016-15 64.96 66.24 64 65.95 5
bash-3.2$
At this stage I wish to add and element to the arrays to obtain the following:
Year 2015 45.935 62.6 43.4 59.14 256
Month 2016-03 63.9 66.69 62.36 65.47 21
Week 2016-15 64.96 66.24 64 65.95 5
I have tried a variety of methods, but until now I am unsuccessful. I have played around with unshift, but none of my attempts have resulted in a satisfactory outcome.
In the remainder of the code, I combine the arrays:
#Combine Year, Month and Week Array into one
my #stashRecent = #stashYear;
push (#stashRecent, #stashMonth);
push (#stashRecent, #stashWeek);
#Convert Array in Latex::Table compatible format
my $recentData = \#stashRecent;
And subsequently I pass it on to LaTeX::Table to generate the required table:
$table = LaTeX::Table->new(
{
data => $recentData,
}
);
$table->generate();
print $table->generate_string();
It get the expected output:
bash-3.2$ ./test.pl DG.PA
\begin{table}
\centering
\begin{tabular}{lrrrrr}
\toprule
2015 & 45.935 & 62.6 & 43.4 & 59.14 & 256 \\
2016-03 & 63.9 & 66.69 & 62.36 & 65.47 & 21 \\
2016-15 & 64.96 & 66.24 & 64 & 65.95 & 5 \\
\bottomrule
\end{tabular}
\end{table}
bash-3.2$
Despite I manage to combine the arrays and convert them into the format required by LaTeX::Table, I have not succeeded to add the elements (Year, Month and Week), as described above.
Any feedback to get me going and improve my knowledge will be highly appreciated. In the mean time, I thank everybody who to give this some thought, and help a newbie with becoming a little less newbie.
I'm not sure I understand the question fully, but it seems the following should do the work:
unshift #stashYear, 'Year';
unshift #stashMonth, 'Month';
unshift #stashWeek, 'Week';
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.)
Disclaimer: you might need to install
a font/typeface which supports
Japanese if you see messed up
characters.
I'm trying to replicate what I've been doing so far with setlocale and strftime:
setlocale(LC_ALL, 'ja_JP.utf8');
$time = mktime();
echo strftime('%x', $time), '<br>';
Output:
2010年01月06日
Using Zend_Date - but I haven't been able to reproduce the same formatting with the japanese symbols for year, month and day.
Attempt #1:
$locale = new Zend_Locale('ja_JP');
$date = new Zend_Date( strtotime('yesterday'), null, $locale);
//echo $date->toString('YYYY abcdefghijklmnopqrstuvwxy M dE');
echo $date->get('YYYY MMM DD');
Output:
2010 1月 004
Attempt #2:
echo $date->get(Zend_Date::DATE_FULL);
Output:
2010年1月5日火曜日
My first attempt I can't seem to find a working constant to produce the YEAR and day symbols. The latter uses a standardized format but I need to customize it so there's a 0 preceding the month, and I want to be more in control.
In the future I may want to make it flexible so for example, en_US dates won't have those letters coming after the year/month/day but it would only apply to languages such as Japanese and others, where it's more common, or if I misunderstood and it isn't really common then please inform me.
Thanks in advance.
Seems what I needed was the DATE_LONG constant, which internally points to 'FFFF' - I'm trying to learn the inner workings of how the Date class corresponds with the Locale class to generate the whole string including the symbols now.
Update: I kept trying to find where it actually used date units instead of date formats, found the right data I need:
<dateFormatLength type="long">
<dateFormat>
<pattern>y年M月d日</pattern>
</dateFormat>
</dateFormatLength>
So it parses this and replaces the y, M, d, returns the formatted date.
I am getting a date field from the database in one of my variables, at the moment I am using the following code to check if the date is in "yyyy-mm-dd" format
if ( $dat =~ /\d{3,}-\d\d-\d\d/ )
My question, is there a better way to accomplish this.
Many Thanks
The OWASP Validation Regex Repository's version of dates in US format with support for leap years:
^(?:(?:(?:0?[13578]|1[02])(/|-|.)31)\1|(?:(?:0?[1,3-9]|1[0-2])(/|-|.)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:0?2(/|-|.)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(/|-|.)(?:0?[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$
The Regular Expression Library contains a simpler version along the lines of the other suggestions, which is translated to your problem:
^\d{4}-\d{1,2}-\d{1,2}$
As noted by others, if this is a date field from a database, it should be coming in a well-defined format, so you can use a simple regex, such as that given by toolkit.
But that has the disadvantage that it will accept invalid dates, such as 2009-02-30. Again, if you're handling dates that successfully made it into a date-typed field in a DB, you should be safe.
A more robust approach would be to use one of the many Date/Time modules from CPAN. Probably Date::Manip would be a good choice, and in particular check out the ParseDate() function.
http://metacpan.org/pod/Date::Manip
How about
/\d{2}\d{2}?-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/
\d could match number characters from other languages. And is YYY really a valid year? If it must be four digits, dash, two digits, dash, two digits, I'd prefer /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/ or /^[12][0-9]{3}-[0-9]{2}-[0-9]{2}$/. Be aware of space characters around the string you're matching.
Of course, this doesn't check the reasonableness of the characters that are there, except for the first character in the second example. If that's required, you'll do well to just pass it to a date parsing module and then check its output for logical results.
The best and lightweight solution is using Date::Calc's check_date sub routine, here's an example:
use strict;
use warnings
use Date::Calc qw[check_date];
## string in YYYY-MM-DD format, you can have any format
## you like, just parse it
my #dt_dob = unpack("A4xA2xA2",$str_dob_date);
unless(check_date(#dt_dob)) {
warn "Oops! invalid date!";
}
I hope that was helpful :-)
Well you can start with:
/\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|30|31)/
I would very strongly recommend AGAINST writing your own regular expression to do this. Date/time parsing is simple, but there are some tricky aspects, and this is a problem that has been solved hundreds of times. No need for you to design, write, and debug yet another solution.
If you want a regular expression, the best solution is probably to use my Regexp::Common::time plugin for the Regexp::Common module. You can specify simple or complex, rigid or fuzzy date/time matching, and it has a very extensive test suite.
If you just want to parse specific date formats, you may be better off using one of the many parsing/formatting plugins for Dave Rolsky's excellent DateTime module.
If you want to validate the date/time values after you have matched them, I would suggest my Time::Normalize module.
Hope this helps.
I think using a regex without outer check is much to complicated! I use a little sub to get it:
sub check_date {
my $date_string = shift;
# Check the string fromat and get year, month and day out of it.
# Best to use a regex.
return 0 unless $date_string =~ m/^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
# 31. in a month with 30 days
return 0 if ($3 >= 31 and ($2 == 4 or $2 == 6 or $2 == 9 or $2 == 11));
# February 30. or 31.
return 0 if ($3 >= 30 and $2 == 2);
# February 29. in not a leap year.
return 0 if ($2 == 2 and $3 == 29
and not ($1 % 4 == 0 and ($1 % 100 != 0 or $1 % 400 == 0)));
# Date is valid
return 1;
}
I got the idea (and most of the code) from regular-expressions.info. There are other examples too.