DateTime - Timezone Offset and Inclusion of Daylight saving time - php

I know that questions about this topic have been asked over and over again, but all the reading just increased my confusion, so I decided to ask here.
I am working on a website where user can store Events, which are connected to a date. This date is stored in a mysql Database as type DATETIME.
So what I "just" would like to do is: Get the date from the Database and format it, but somehow, since the start of the Daylight Saving Time, ech date is shown minus one hour.
code:
$date = $item['date'] //<-- the result from the database (2015-11-27 08:15:00)
$dt = new DateTime($date, new DateTimeZone(date_default_timezone_get()));
echo $dt->format('G:i') // 8:15
The Value which was actually written in the "Date Field" of the administration form is 9:15 and that is what should be displayed.
Please correct me if I am wrong, but I think that "Summertime" seams to the common Basis. And the shift to "Wintertime" might be +1.
echo $dt->getOffset() // 3600s = 1 hour
If my assumtion is right, that offset should be zero in "Summertime", right? But that leads to the point I cannot sort out, since I am in the Timezone Europe/Berlin what itself is defined to be UTC +1
So which Offset does this getOffset() represent and how can I display the "right time"?
Thanks in Ahead!

Related

Advice for php time zone settings

I live in Denmark - but am setting up a page for a friend in USA (Washington State). The page is hosted at Surftown, in Denmark.
I know there is a 9 hour difference, so I set:
date_default_timezone_set('America/Los_Angeles');
But there is something I obviously don't quite understand about time zones / date() and strtotime() because:
Via text input I am trying to save a specific date and time to the database.
Lets say that $_POST[date] input is: '01/29/2015' and $_POST[time] input is: '02:00 PM'.
I then create a stamp using:
strtotime($_POST[date].' '.$_POST[time]);
But when I try to output this, I get the correct date - but 9 hours is added to time? Why is this?
I guess I could just remove the time zone setting for this specific task - but
I'd like to understand why. I am setting the time zone because I also need to save some timestamps based on the actual time of the user (in Washington state - not Denmark).
Can you help?
strtotime assumes you are passing a UTC date so it converts it to the server timezone, what you can do is the following:
$date = new DateTime($_POST[date].' '.$_POST[time], new DateTimeZone("UTC"));
echo $date->getTimestamp();

PHP: right way to manage DateTime (timestamp Y2038 Bug aware!)

In my "tool box" i'm using this function:
function dataAttuale() {
$now = new DateTime();
$dataAttuale = $now->format(DateTime::ISO8601);
$offset = $now->getOffset();
date_default_timezone_set('UTC');
$nowUTC = new DateTime();
$dataUTC = $nowUTC->format(DateTime::ISO8601);
$orario = array();
$orario['dataAttuale'] = $dataAttuale;
$orario['dataUTC'] = $dataUTC;
$orario['offset'] = $offset;
return $orario;
}
I get this array
Array
(
[dataAttuale] => 2013-10-18T11:03:52+0200
[dataUTC] => 2013-10-18T09:03:52+0000
[offset] => 7200
)
So i could save in a datetime MySql field a datetime referred to UTC.
Now, i've some trouble about this.
1) I would save also offset (in seconds). What's best Mysql field? I think max seconds can be +14hour * 60 * 60 = 50400 and -12hours*60*60 = -43200
2) Do you think is notable save also offset? I.e., for example, several API services return a date in UTC + offset...
Thank you very much!
UPDATE:
Thank you to both people. Now i'm saving in MySQL datetime in UTC format and varchar timezone. With a couple of code I'm getting what I want:
$orario = new DateTime($value['creazione'], new DateTimeZone($value['timezone']));
$orario = $orario->format(DateTime::ISO8601);
The output is (for Europe/Rome)
2013-10-19T09:27:54+0200
And for America/Montreal
2013-10-19T09:29:16-0400
And for Australia/Melbourne
2013-10-19T09:30:31+1100
(difference of minutes//seconds it the time to change in my PHP scripts the default Timezone).
Now I think that:
1) I can laugh about Y2038 bug, abandoning (sigh :( ) timestamp :(
2) I can safely travel around the world and use my own Calendar (naaaa... i'll use forever Google Calendar, of course)
It doesn't make a lot of sense to save the offset. There are two possible values you can be interested in with a timestamp:
the general global timestamp, e.g. "the point in time in this world at which it was 12:52am on Sept. 6 2013 UTC"
the specific local time of some point in time, e.g. "17:34 on Dec. 19th 2012 in Manila, Philippines"
Notice that both of these are actually the same thing, they express a point in time in the notation of wall clock time and date at a specific location or timezone. The only difference is that UTC is a specified standard "location" relative to which other timezone offsets are expressed; but there's no reason Manila in the Philippines couldn't be used for the same purpose.
So when you want to store an absolute timestamp, you either:
decide that all your times are stored in a specific timezone like UTC and simply store that timestamp
decide that you are interested in a specific local time and store the timestamp and its timezone
Either way you need the timestamp and you need to know which timezone it's in. In 1. you decide in advance that all timestamps are in the same defined timezone and don't need to store it, in 2. you explicitly save that timezone information.
An offset is not a good thing to store, because it varies throughout the year. The offset in summer may be +6 hours to UTC, but in winter may be +7. If you need to do date calculations on a localized time later on, an offset is misleading and doesn't help you much. If you know the timezone you're talking about, you can get the offset for any time of the year later on.
MySQL doesn't support a DATETIME + TIMEZONE field (Postgres for example does), so you need to store the timezone (e.g. "Europe/Berlin") in a separate text field. If you don't need to associate a timestamp with a specific location at all, then there's no need for a timezone and you just need to store the normalized timestamp, e.g. normalized to UTC.
MySQL is award of timezones (it does not store the timezone with the date, but it converts it to a normalized format), so most of the time you do not need to have an additional field with the offset.
You just need to make sure that you set the correct time_zone for your connection.
So if you have a date and you want to store it in your database you have different possibilities:
You can use SET time_zone = timezone; for your connection. Way you tell MySQL that the date you send or receive from MySQL should be in the give timezone. MySQL will internally convert it to a normalized format.
If you want to insert dates that have different timezones then set for the time_zone then you could use CONVERT_TZ(dt,from_tz,to_tz). from_tz is the timezone of your date, to_tz the one that is set for your connection.
There are for sure situations where the timezone could matter. If that is true for your case is not exactly clear out of your question.

PHP date with 30 mins added, is reversed when inserted into MySQL datetime column

I believe I'm going mad.
$expire = date('Y-m-d H:i:s', strtotime("+30 minutes") );
It works as expected when echoed, yet when I insert it into a custom table via the wordpress database class, into a datetime column it's showing current time minus 30 mins.
Am I mad?
Simply given the time frame you are working with, it makes me wonder if you are seeing a Standard/Daylight time conflict, assuming you observe daylight savings time where you are.
First, See if you experience the same issue with "+60 minutes" as a test. If it is then -60 in the database, then it may be a bug, however, if it is then the current time in the database, it may actually be a timezone issue.
Make sure all of your timezones are properly configured on your host OSes and in your database. If the database column is of the type "timestamp" then mysql converts it to UTC on storage, and back on retrieval, so a mis-configured timezone could cause a 1 hour offset there as well.
Hope This Helps!
All date and time functions are now dependent upon a correct timezone setting.
You can either do this in your script
date_default_timezone_set('America/Los_Angeles'); // for example
OR
Check your php.ini for this setting
date.timezone = UTC
And set it correctly for your specific timezone, here is a List of supported timezones which you will need either way

Timezone and Daylight Savings Issues

I've looked through the other solutions on SO and none of them seem to address the timezone/dst issue in the following regard.
I am making calls to NOAA Tide Prediction API and NOAA National Weather Service API which require a time range to be passed for retrieving data. For each location in my database, I have the timezone as a UTC offset and whether daylight savings time is observed (either 1 or 0). I'm trying to format some dates (todays and tomorrow) to be what the LST (Local Standard Time) would be in it's own timezone so I can pass to these API's.
I'm having trouble figuring out how to know if a date, such as todays, is within the daylight savings time range or not.
Here is what I have so far:
// Get name of timezone for tide station
// NOTE: $locationdata->timezone is something like "-5"
$tz_name = timezone_name_from_abbr("", $locationdata->timezone * 3600, false);
$dtz = new DateTimeZone($tz_name);
// Create time range
$start_time = new DateTime('', $dtz);
$end_time = new DateTime('', $dtz);
$end_time = $end_time->modify('+1 day');
// Modify time to match local timezone
$start_time->setTimezone($dtz);
$end_time->setTimezone($dtz);
// Adjust for daylight savings time
if( $locationdata->dst == '1' )
{
// DST is observed in this area.
// ** HOW DO I KNOW IF TODAY IS CURRENTLY DST OR NOT? **
}
// Make call to API using modified time range
...
How can I go about doing this? Thanks.
You can use PHP's time and date functions:
$tzObj = timezone_open($tz_name);
$dateObj = date_create("07.03.2012 10:10:10", $tzObj);
$dst_active = date_format($dateObj, "I");
If DST is active on the given date, $dst_active is 1, else 0.
Instead of specifying a time in the call to date_create you can also pass "now" to receive the value for the current date and time.
However, like Jon mentioned, different countries within the same timezone offset may observe DST while others may not.
For each location in my database, I have the timezone as a UTC offset and whether daylight savings time is observed (either 1 or 0).
That's not enough information. There can be multiple time zones which all have the same standard offset, all observe DST, but perform DST transitions at different times. (Indeed, historically they may also start and stop observing daylight saving time for several years.)
Basically, your database should contain a time zone ID, not the offset/DST-true-or-false. (Assuming PHP uses the zoneinfo time zone database, a time zone ID is something like "Europe/London".)
EDIT: To find the offset of a given DateTime, you can call getOffset, which you can then compare with the standard time offset. But unless you have the definitive time zone ID, you will be risking getting the wrong zone.
Cillosis,
I hope you are not working with Java! I am and fought with time all the time. I also work with weather data. Most of the data I use is in local standard time (ignoring daylight saving time). I also need to use times from other time zones and found that Java kept reading my computer's time zone. I also kept running into deprecated classes. I came up with a solution that works. It is a bit of a kluge, so I have it heavily documented and it only exists in one function. My solution is relative time. I have set the local time to UTC. I am subtracting the GMT offset instead of adding it. I don’t really care about the actual times, all I care about is the difference between two times. It is working very well.
Good luck

Setting time according to timezone from database

I want to make a system which displays time dependant on the timezone in a particular country. E.g. a table in my database contains country names in one field, and in the column next to it, it will contain GMT-compared timezones like -0100 or -0200.
What I need to do on the webpage then is set current GMT time ($time), and then pull the information from the database and alter $time to be GMT -1 or GMT -2.
Could someone tell me what the easiest way to do this would be please?
Thanks for any help
Edit:
So far I have this code:
<?php
$time = date("H:i:s", time());
echo $time;
echo "<br/><br/>";
$myDateTime = new DateTime($time, new DateTimeZone('GMT'));
$myDateTime->setTimezone(new DateTimeZone('Antarctica/South_Pole'));
echo $myDateTime->format('Y-m-d H:i');
?>
which seems to do the job, and I could enter into the database 'Antarctica/South_Pole' rather than the GMT-/+ time. Would this do the job OK in the long run?
Also, using this method, would Daylight saving times be worked out OK?
Using the DateTimeZone is the correct way to go about it.
If you provide it with zoneinfo keys (such as America/New_York, or Antarctica/South_Pole as in your example) Daylight Saving time WILL be factored into the result, which is not the case if you have a naive database with only the UTC offset stored.

Categories