Question

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!

Was it helpful?

Solution 2

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

OTHER TIPS

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

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];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top