How to set time zone in PHP - php

I have a site that has list of stores in different countries ( different time zones ), and it should display when store is OPEN or CLOSED by working hours.
I have javascript that gets DEFAULT timezone GMT offset when daylight saving isn't set, put it inside mysql, and that part works correctly.
My timezone is GMT+1 ( and now it's daylight saving active, so it's +1 hour now )
I use php to change zone using this:
date_default_timezone_set('Etc/GMT+1');
echo date('h');
Time here: 10 PM
GMT time: 8 PM
And this code return: 7 PM
So it's like it instead increasing by 1, it decrease, and plus there is no daylight saving...
Can someone tell me what happen here?
Is it php bug or something wrong on server?
Thank you...

I'm currently chuckling because I recently had a similar problem. Unfortunately Etc/GMT timezones are deprecated. They break. My personal recommendation? Just use HH:MM or set it by the city (cities don't require daylight savings time adjustments!)

Perhaps date('I') might help in this situation.
Unless there is an option to define a look-up list [GMT offset] - [time zone name]. Then it will be possible to adjust time zone using DateTime\DateTimeZone classes.

Related

Some questions about EDT and time difference

Introduction to my website
My website is for visitors in Korea(AKA Republic of Korea).
And the server for My website is in the United States of America.
And PHPMyAdmin displays EDT when it runs a query SELECT ## system_time_zone.
Structure of my website
When I first uploaded my website to this server in October this year, I checked the DB time.
And it seemed that there was a time difference of 13 hours with Korea. So I added 3600 * 13 seconds to DB time(without setting timezone) as follows.
const Offset = 3600 * 13;
$SelectNow = $PDO->prepare('SELECT DATE_ADD(NOW(), INTERVAL '.Offset.' SECOND)');
$SelectNow->execute() or exit;
$DbNow = $SelectNow->fetchColumn();
My website takes $DbNow as above and uses it in various situations.
For example, in the posting situation, enter $DbNow in the datetime field of the INSERT INTO query as follows:
$WriteNote = $PDO->prepare('INSERT INTO table_note(my_datetime, my_contents) VALUES("'.$DbNow.'", :my_contents)');
$WriteNote->bindValue(':my_contents', $my_contents, PDO::PARAM_STR);
$WriteNote->execute();
The problem situation
One day in November of this year, when I wrote a post and checked the date field(my_datetime) of the post, I got an additional time difference of one hour with Korea.
Apparently, at the end of October, I corrected the time difference of 3600 * 13. And then I confirmed that it matches the Korean time. However, in November, There is a time difference of one hour!
Guess the cause
It seems that US summer time is being applied to the DB server of my website. Did I guess right?
My question
1) How can I solve this time difference fundamentally?
Is it correct to convert DB time to KST?
Or is it the correct way to convert to UTC and then added 3600 * x to UTC?
2) Even though the problem is resolved, some of the existing data in my DB has a time difference of one hour with Korean time.
What query do I use if I want to select the data with a time difference?
And how much more or subtract it from the data to get rid of the 1 hour time difference?
Use UTC to store time in Database.
change your queries to insert with UTC datetimes.
Use external libraries to convert UTC to respective timezones.
(below are the my personal recommendation.)
There may be best of it.
PHP : Carbon
Javascript : Moment, moment timezone.
No, it takes timezone of Database server resides in.
little manual verification, or create a job to change all dates in UTC.
Edit:
http://carbon.nesbot.com/docs/
I mean you can create a script and run with cron job.

How to calculate average time of day taking into account timezone differences?

I'm using Laravel/PHP/MySQL and storing all dates and times in UTC.
The user can select a timezone (for example Eastern), enter a date and time, and the date and time will be converted to UTC before storing. On retrieval it will be converted to user's selected timezone.
My question is how can you get the average time of day from a series of records taking into account the timezone (preferably in the database query)? The following question addresses average time of day in PHP, but not the timezone issue.
How to calculate average time
Here is what I'm doing:
SEC_TO_TIME( AVG( TIME_TO_SEC( TIME(flights.departed_at) ) ) ) ) AS average_time
This works except for records that span daylight saving/standard time in a region that observes it.
FOR EXAMPLE: You may have a record with the UTC datetime of 2015-08-18 11:00:00 that was entered by a user in EDT at 2015-08-18 07:00:00. Then you have a second record entered with the UTC datetime of 2015-11-10 12:00:00 by a user in EST at 2015-11-10 07:00:00. If you try to calculate the average time of day it should equate to 07:00:00 but instead the result is 07:30:00.
Any ideas how to overcome this? Am I approaching this all wrong?
Thanks in advance.
In short, your code is working correctly. Once the date is in UTC, you'd have to re-calculate whether or not it was entered (1) during daylight savings time, (2) by someone actually observing daylight savings time, and (3) in a place that recognizes daylight savings time.
I can really only think of one way to approach this.
Add some kind of flag when the data is saved to mark the timestamp as DST. You can use this flag to adjust for the hour difference. How you generate this flag is up to you.
If you have all your times stored in Z, and if your MySQL database has the timezones loaded correctly, you can use the zoneinfo timezone name to retrieve your local times. For example,
SELECT CONVERT_TZ('2015-08-01 11:00', 'UTC', 'America/New_York'),
CONVERT_TZ('2015-12-01 12:00', 'UTC', 'America/New_York')
yields
2015-08-01 07:00 2015-12-01 07:00
The point is, the zoneinfo database knows to use daylight saving time or standard time for each datetime value. It doesn't use the current offset, it uses the offset in effect on the date in question.
So, you can retrieve the time of day, in local time, with an expression like this:
TIME(CONVERT_TZ(utc_time_column, 'UTC', 'America/New_York'))
Then, you average those times-of-day in the usual way.

How to deal with timezones between server and client?

I'm developing a website where I have to deal with different possible timezones from the users. This becomes a great problem since the website hosts time-delicate events like auctions.
All dates/times on the server are in UTC. Database stores everything in UTC timestamps. PHP default timezone is set to UTC too (date_default_timezone_set('UTC');).
Now, my problem is how I should interact with the users, whether I'm only showing a date or, more important, I'm reading a date/time from user input.
A concrete example:
An auction has a deadline, which I store in database as UTC.
When I view the auction on the website, a javascript timer uses a Date object to calculate the remaining time. It automatically converts the timezone to GMT+0100 (my local timezone). So if the deadline is '2013-08-08 10:46:08' (UTC), the javascript date object will return Aug 08 2013 11:26:15 GMT+0100 (GMT Standard Time).
If the current time is greater than 11:46:08 then the timer says that the remaining time is 00:00 (which is correct).
But if I try to insert a bid, the server accepts since the condition on the MySQL INSERT evaluates to true:
INSERT INTO Bids ... WHERE ... AND auction_deadline > NOW() ...
( because auction_deadline = '2013-08-08 10:46:08' and NOW() = '2013-08-08 10:26:50')
All this mumbo jumbo of timezone melts my brains. What am I missing here? I'm almost certain that storing all dates/times in UTC inside the database is the best. I just can't think crystal clear how do deal with it between the user and the database.
Your problem doesn't involve timezones at all, just the fact that clients can turn their clocks or have their clock skewed considerably. For that the fix is to poll the server every once in a while for an offset fix to use in calculations.
In fact, you don't even need date objects. There is a certain universal instant in time when the auction ends. Let's say it is 1375960662823. Right now, the universal instant in time is 1375960669199, so from that we see that the auction ends in 6 seconds (1375960662823 - 1375960669199 ~ 6000 ). It will end in 6 seconds regardless if I am in Morocco or Japan. Do you understand it yet?
To generate these numbers, on the client side you can call var now = Date.now() + skewFix where skewFix is the correction that needs to applied in case client has time skew or manually set their computer to wrong time.
In PHP, you can generate it with $now = time() * 1000;
This is rather a typical subject yet very complex for most to understand. First thing, you never mention the DAYLIGHT SAVING. yeah I am increasing your tension :).
Now let us see how we can do this. You did a good job by saving the Time in UTC. Now, I hope you have registered members and that each member has ability to set their preferred timezone, otherwise you will show Server' timezone based time to them.
When you through "start time" to user you must send them after converting UTC time to their time, similarly when you accept TIME from browser be it user action or javascript you need to convert that time to UTC considering the fact that user is that time zone that he select for his profile.
Hope that clear the idea on where you are going wrong? Please read through day light saving as that will play an important role too when you move ahead with other logic on same.
EDIT:
You can use javascript's Timezone offset, for auto submission and user input based on his settings.
Date in JavaScript uses local timezone. You should get UTC time for the user and send it to the server
new Date
Thu Aug 08 2013 17:00:14 GMT+0530 (India Standard Time)
(new Date("Thu Aug 08 2013 17:00:14")).toUTCString();
"Thu, 08 Aug 2013 11:30:14 GMT"
This will resolve the timezone issue between the server and client.
You said
( because auction_deadline = '2013-08-08 10:46:08' and NOW() = '2013-08-08 10:26:50')
In MySQL - NOW returns the current time in the server's local time zone (docs).
You probably want something like UTC_TIMESTAMP which returns the current time in UTC (docs).
Also - you probably shouldn't accept any input time from the client JavaScript at all. Only trust your own clock. When a bid is placed, use the time on your server in MySQL or in PHP. Don't accept it as input.
You can do the following
once page is loaded, send an ajax request to server with timezone offset of user. You can get timezone offset using the following code.
var curdate = new Date()
var offset = curdate.getTimezoneOffset()
offset is timezone offset in minute.
I think it will help.
everytime when you get the date from the clientside, you can use the getUTC to convert to UTC date ie:
var todayDate = new Date();
var todayDateInUTC = new Date(todayDate.getUTCFullYear(), todayDate.getUTCMonth(), todayDate.getUTCDate(), todayDate.getUTCHours(), todayDate.getUTCMinutes(), todayDate.getUTCSeconds());
so right before you insert the bid date to database, use the getUTC functions to convert it into UTC format.

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

Mysql Current Timestamp and time() showing different values

OK. So I have been trying to implement a timer. Now a very weird thing is happening and I can't understand why ?.
Basically I am trying to find the difference between the last access and the current time. I am storing the time of last access in the database. This value is according to the server time. But when I try the time() function of php it shows me values which are 5-6 hours behind the time that I have in the database.
For example: here is my code :
$t1= strtotime($played_row->timer); // Time from the database with CURRENT_TIMESTAMP
$t2= strtotime("now"); // Get the current time
It shows Year: 2012 Month: 01 Day: 21 - 05:28 pm for t2
and Year: 2012 Month: 01 Day: 21 - 10:28 pm for my timestamp values.
Can anyone tell my why is that ?
P.S: I am running the code on my computer itself.
At a guess I would say that your database and PHP are using two different timezone offsets.
Most likely this is a timezone issue: if you are in the Eastern timezone, you are 5 hours away from UTC right now. If one sytem is returning local time and another is returning UTC this is what you will see.
Try using date_default_timezone_set() to set the timezone in PHP that is used in your database.
date_default_timezone_set — Sets the default timezone used by all
date/time functions in a script
Alse see date_default_timezone_get() how to get ini-set timezone.

Categories