March 14th not 86400 seconds long? - php

In my web application, I have users input a date in a simple textbox. That input (after being sanitized, of course), is run through strtotime(), and 86399 is added to it, to make that timestamp the end of the day written (11:59:59). This is for due date purposes (so if the date passes, the application raises a flag)
For the days I tested, it worked...
January 5th saved as january 5th, at the end of the day.
March 13th saved as March 13th
March 15th saved as March 15th
March 14th, for whatever reason, saved itself as March 15th.
Is March 14th mysteriously a couple seconds short or something??
Update: Thanks to oezi for the solution - worked like a charm. Code as requested:
Old code:
if ($_POST['dateto'] != '') {
$dateto = strtotime(mysql_real_escape_string($_POST['dateto'])) + 86399;
}
New code:
# Offset to "end of day"
list($y,$m,$d) = explode('-',date("Y-m-d",strtotime($_POST['dateto'])));
$d++;
$dateto = strtotime($y . '-' . $m . '-' . $d) - 1;

March 14, 2010 is the day Daylight Saving Time begins in the United States. So if you're doing math in the local time zone, March 14 is only 23 hours long.

I would assume because this is the beginning of daylight savings time

Like others said, this is because of daylight saving time. To solve this problem, you could do this:
<?php
list($y,$m,$d) = explode('-',date("Y-m-d",strtotime($date_from_user)));
$h = 23;
$i = 59;
$s = 59;
$mytimestamp = "$y-$m-$d $h:$i:$s";
?>

What database are you using? there has to be a better way to do this (most date manipulation commands are database specific). In SQL Server, I'd just add 1 day to the date and then subtract 1 second:
DECLARE #YourDate datetime
SET #YourDate='2010-03-14'
SELECT DATEADD(ss,-1,#YourDate+1)
OUTPUT:
-----------------------
2010-03-14 23:59:59.000
(1 row(s) affected)
for what it is worth, I'd much prefer to have a condition: < NextDay than <=CurrentDay12_59_59

In all time zones that "support" daylight savings time, you'll get two days a year that don't have 24h. They'll have 25h or 23h respectively. And don't even think of hardcoding those dates. They change every year, and between time zones.
Oh, and here's a list of 34 other reasons that you hadn't thought about, and why you shouldn't do what you're doing.

http://tycho.usno.navy.mil/leapsec.html
Not all days are 86400 seconds long.
This is a rare event. And (historically) never scheduled in March.

Related

PHP - Parsing String As Past Date

Currently, I'm trying to parse out dates when messages were received into timestamps. I have the month and day but the year is not specified. The event always occurs at the most recent (human) reading of the time. It works great in most cases to do this:
$time = strtotime("Jan 2 8:38pm");
That returns a date for this year, which is correct. Unfortunately, I get problems when I try to do for example:
$time = strtotime("Dec 31 8:38pm");
That returns a date which hasn't happened yet, and wont happen for the whole rest of the year. Obviously, my message was not sent in the future. I need it to return December 31st of last year.
For weekdays, I had a solution by prepending 'last' before the weekday like so:
$time = strtotime("Last Saturday 8:38pm");
That always returned the time of the last Saturday. However, trying to do the same thing here doesn't work:
$time = strtotime("Last Dec 31 8:38pm");
This returns false. I know to decrement a date by 1 year, I can do this:
$time = strtotime("Dec 31 8:38pm -1 year");
And that works great for Dec 31. However, Jan 2 will now fail:
$time = strtotime("Jan 2 8:38pm -1 year");
One solution I thought of was to subtract off a year (86400 * 365) from the resulting value if it is past today's date. However, this result will fail if we passed over February of a leap year. In that case, we would end up with a time that was ahead by a day.
The best solution I came up with so far is this:
$time = strtotime($raw_time);
if ($time > time()) {
$time = strtotime($raw_time." -1 year");
}
It seems kind of wasteful to make two calls to strtotime which I know is probably not a very efficient function. Is this the most elegant solution?
Is anyone aware of an option in strtotime which forces the dates to be in the past instead of in the future?
Is there another way to parse these dates that I should consider?
Efficiency is important for this because I am going to be parsing a lot of dates with it, but I would also like simple and readable code so I can understand it later.
Your approach is fine, as there is no date format to get what you want. Another approach could be using the DateTime class:
$datetime = new DateTime($raw_time);
if ($datetime > new DateTime()) {
$datetime->modify('-1 year');
}
You could test which one of the two approaches is faster. My guess is that this is a micro-optimization that won't make a lot of difference.

Go over 24 hours in a date?

I am working on project (a Google Transit feed) where I am required to provide the times for each stop on a bus route in the following common format: 21:00:00 and so forth.
Problem is, if times continue past midnight for a given trip, they require it to continue the hour counting accordingly. They explain quite specifically that 02:00:00 should become 26:00:00 and 03:45:00 should become 27:45:00 etc.
I am baffled on how to display such with any of the date() or strtotime() functions.
The only thing I can think of in my particular situation would be to function match and replace any strings in my output between 00:00:00 and 04:00:00, as that would clearly mean (again, for me only) that these are trips originating before midnight, but I don't feel that's the correct way.
Well seeing as it's only displaying on the page, you can
firstly get your date from where ever
Let's say $date = 00:00:00
$exploded_date = explode(":", $date);
This takes $date and puts it into an array so
$exploded_date[0] is hh
$exploded_date[1] is mm
$exploded_date[2] is ss
Then what you can do is use ltrim() to remove the leading 0 from 00 to 04 $exploded_date[0] - This makes it comparable in the if statement I'll do after
if($exploded_date[0] <= 4) {
$exploded_date[0] = ltrim($exploded_date[0], "0");
$exploded_date[0] = $exploded_date[0]+24;
}
Then you can implode the array back together into one string
$date = implode(":", $exploded_date);
// if the hour is 00 to 04 it will come out as 24 to 28
// e.g. 24:35:30
echo $date;
Despite giving you an answer. It's a silly thing to be doing, but it's not your choice so here you go :)
The way you display something doesn't necesarily has to be the same way you store something.
I don't know how you calculate the times, but assuming you have a start date and time, and some interval, you could calculate the end time as follows:
date_default_timezone_set('Europe/London');
$start_datetime = new DateTime('2014-11-11T21:00:00');
$next_stop = new DateTime('2014-11-12T02:00:00');
echo $start_datetime->format('Y-m-d H:i'); // 2014-11-11 21:00
echo $next_stop->format('Y-m-d H:i'); // 2014-11-12 02:00
$interval = $start_datetime->diff($next_stop);
// display next stop: 2014-11-11 26:00
echo ($start_datetime->format('Y') + $interval->y) .'-'
. ($start_datetime->format('m') + $interval->m) .'-'
. ($start_datetime->format('d') + $interval->d) .' '
. ($start_datetime->format('H') + $interval->h) .':'
. ($start_datetime->format('i') + $interval->i);
What I'm doing: create the start date (& time) and the datetime of the next stop. With the DateTime::diff() function I'm calculating the difference, and then, only for display (!) I add up each year, month, day, hour and minute to the datetime year, month etc. of the next stop.
This way you can still store your dates and times in a way every human being and computer system will understand (because let's be honest; to represent a time as 27:45 PM is quite ridiculous...)
I don't know if you only want the hours to be added up and roll over the 24 hour, or also days in a month etc. It's up to you how you handle these cases. Good luck!

Strange php date sum behavior

Why does this sum only 4 days when using 25-Oct-13 and 5 days (as expected) when using other dates?
<?php
echo date('d-M-y',(strtotime('25-Oct-13') + (432000)));
?>
This depends on your timezone. The last Saturday of October is the end of Daylight Saving Time (DST) in some locales. Therefore the night of October 26th to 27th in 2013 may or may not contain an extra hour.
Circumvent this issue by adding actual days instead of hours:
$myDate = new \Datetime('2013-10-25');
$myDate->add(new \DateInterval('P5D'));
This does return Oct 30th 2013.
More strange stuff can happen from incorrectly assuming that days are always exactly 24 hours.
$date = "2014-09-17";
echo date('Y-m-d', strtotime($date.' + 5 days'));

Counting down days not showing the right number of days

I need help.. Is this right?
Start Date: Mar 16, 2014
End Date: Mar 19, 2014
Results: 2 Days
$plantEnd = get_the_author_meta('plantEnd', $sellerID );
$plantStart = get_the_author_meta('plantStart', $sellerID );
$future = $plantEnd;
$d = new DateTime($future);
echo $d->diff(new DateTime())->format('%a').' Days';
Why does it says 2 days? Isn't it 3 days? Im confused..
Since you aren't actually using $plantStart in your code and instead using the current time, you're basically getting a difference between now (the time the script was run, on server's time zone) and the start of Mar 19, 2014 (0h:0m:0s). So what you are really getting is something like 2 days 5 hours 3 minutes 25 seconds (depending on when you run it vs. server time.
for example, when I run this locally:
$d->diff(new DateTime())->format('%d:%H:%i:%s');
I get 2:04:59:25
So there's more to it than just getting that "2" returned.. you're just not formatting for it.
And again, you aren't actually using the $plantStart anywhere either. So if you were to do this:
<?php
$plantEnd = '2014-03-19';//get_the_author_meta('plantEnd', $sellerID );
$plantStart = '2014-03-16'; //get_the_author_meta('plantStart', $sellerID );
$future = $plantEnd;
$d = new DateTime($future);
echo $d->diff(new DateTime($plantStart))->format('%d:%H:%i:%s');
?>
You will see it outputs 3:00:0:0 (or you could continue to just use %d and get the "3"). This is because $plantStart (presumably - based on your post) just specifies yyyy-mm-dd, so passing just the yyyy-mm-dd value will put the hh:mm:ss at 0:0:0 (beginning of day) , so it will be a full day's calculation, which has the effect of "rounding up" to the whole day increment.
I have a feeling that it's actually 2 days, someodd hours, and someodd minutes, or something to that effect. Because you're formatting to just do days, you're losing the nuances. I'd change the code to say "2.4 days" (and for the life of me I can't remember how I did this in the past...)
EDIT: in the past I have simply used date() instead of DateTime().
I did a little research, and you might want format('%d')." Days";

php mktime gives different results for same date?

the following code:
// settings 1st alternative
$season = 2011;
$startweek = 36;
// calculation, 1st alternative
// in any case Jan 1st is in 1. week
$firstweekuniversal = mktime(0,0,0,1,4,$season);
// I'd like to calculate monday 0:00 of the given week.
// date(...) computes to monday of the calculated week.
$startday1 = $firstweekuniversal + 86400 * (7*($startweek-1) - date('w', $firstweekuniversal)+1);
// settings 2nd alternative
$StartingDate = "KW36 - 5.09.2011 (Mo)";
// calculation, 2nd alternative
$firstparts = explode(" ", $StartingDate);
$secparts = explode(".", $firstparts[2]);
$startday2 = mktime(0,0,0,intval($secparts[1]),intval($secparts[0]),intval($secparts[2]));
// Output
echo "Start: \$startday1=".$startday1.", Timestamp=\"".date("d.m.Y - H:i:s", $startday1)."\"<br>\n";
echo "Start: \$startday2=".$startday2.", Timestamp=\"".date("d.m.Y - H:i:s", $startday2)."\"<br>\n";
leads to this output:
Start: $startday1=1315177200, Timestamp="05.09.2011 - 01:00:00"
Start: $startday2=1315173600, Timestamp="05.09.2011 - 00:00:00"
where is the 1h difference coming from? It can't be summertime issues, in that case the 1h had to be the other way round, or am I wrong?
There's no difference, when I'm trying with my environment (localhost), but on the server of my prvider there is.
Can anyone explain this to me? I'm totally puzzled here.
Thanks in advance,
My understanding of daylight savings is that at a certain point between winter and summer the sun is starting to rise earlier, so at 8am it would feel like it should be 9am ... and that's exactly what the clock does, it moves forward making it later (by one hour typically). This is also why it's such a good excuse for being late at school :)
In any case, the timezone setting of your local php is probably UTC (or some other "neutral" timezone) but the server timezone setting honors daylight savings.

Categories