Timezones and cron - php

I have a MySQL database containing details of shops in different time zones. The timezone of each store is stored in iana format and the MySQL datetimes are stored in UTC.
I wish to execute some php code at the end of the day for each shop.
This is how I am thinking to approach this but is there a better way?
Set a cron to run hourly at xx:59:59.
Get the current date at the top of the php script. Is the script guaranteed to get the correct date at 23:59:59?
Use SQL query to return all shops that are at the end of the current day. I'm not sure how to check this in the query?
Perform the end of the day processing on those stores.

You can run an hourly cron job any time you wish.
Why do you need the date here? You wrote that you're interested in the servers, which are at 23:59:59 localtime, so time is relevant, I think, not the date. Also, if your details server is very busy, your script might run too late and get the next day's date.
If IANA time zone format means offset to UTC, you could simply look for shops having a timezone like
24 - current time(UTC) +/- DST
Negative timezone offsets work similar, e.g. 24 + offset. So timezone offset -01:00 would become +23:00
Nothing to say here.

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.

MySQL Query "How long ago" + 6hours

With the help of a friend, I got a webpage going that tracks different stats and saves it in an SQL database.
One of the information that returns, is when the latest score was submitted to the database. It works fine, but the webhost is in a different timezone and I am unable to change that timezone.
So therefore I was thinking about changing our query to one which returns how long ago the score was added.
Current code:
$statement = $adapter->query("
select name,
SUM(score_1) as score_1,
SUM(score_2) as score_2,
SUM(score_3) as score_3,
(SUM(score_1)+SUM(score_2)+SUM(score_3)) as total,
DATE_FORMAT(MAX(creation_time), '%d %b %H:%i') as creation_time
from score_entry
WHERE DATE(creation_time) = CURDATE()
group by name ORDER BY total DESC");
It grabs the information stored in the past day (from 00:00 this day), and I'm not sure if that is also affected by the incorrect timezone.
After a lot of searching around, I can't seem to find the solution to my exact problem.
I have tried to set the timezone in MySQL, but it's a shared host by Namecheap, they don't allow it.
Take a look at the time zone documentation.
Using the SET time_zone = timezone; command you will be able to set the time zone on a per-connection basis.
In addition, storing dates in a TIMESTAMP column makes MySQL convert the time to UTC and then it converts it back to the current time zone when you access it. Thus it makes storing and retrieving time zone agnostic.
Set the time zone in your PHP script using the posted solution. It's also possible to send it the datetime to use in your query using PHP's date function.

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 + PHP Timezone Issue

I currently use $curdate=date('Y-m-d H:i:s'); to enter a timestamp to my blog's MySQL.
The problem is that the timezone of my MySQL is 2 hours ahead. At least in the timesaving period (I don't know if it is going to be any different when the timesaving period is over).
How should I redefine $curdate so that it records correct time based on PST time?
You can set the timezone the PHP uses for the duration of the execution of your script with date_default_timezone_set().
If you need to do something in your own timezone later in the execution of you script, you can call it again to set it back.
Alternatively (better?), if you use the MySQL NOW() function in your query, the time entered into the database will be calculated by MySQL, according to it's own timezone.

How to get UNIX_TIMESTAMP to not offset a datetime field when in different time zones?

I have built a small forum where users can post messages. My server is in the United States, but the userbase for the forum is in Taiwan (+15hrs).
When someone posts to the form, I store the time in my mySQL database in the format YYYY-MM-DD HH:MM:SS. When I look in the database, the time displays the proper time (the time that the person in Taiwan posted it).
However, when I use UNIX_TIMESTAMP to get the date out of the database, the time is altered.
Example:
I post something to the forum. The datetime on my wrist watch is 2009-10-2 11:24am (Taiwan Time)
I look in the database and it says the datetime is 2009-10-2 11:24am (same time as my wrist watch. good!)
Then when I use UNIX_TIMESTAMP to display the date on my website, it shows as 2009-10-03 4:22 pm (bad! it applied an offset)
Is there a way I can get UNIX_TIMESTAMP to stop converting the time (applying an offset) when I query the date from the database?
Extra Info:
I'm using PHP
I have set the timezone in my PHP to Taiwan (date.timezone = Asia/Taipei)
If a user is in another timezone than Taiwan, I want it to convert the time to Taipei time. The site is nearly 100% Taiwan used so I just want Taiwan time to show all the time even if they're in another timezone.
I display the date in lots of areas around the site in different date() formats.
Basically everything works great except that when I use UNIX_TIMESTAMP to query the data out, it applies an offset to the time.
Thanks!
MySQL writes dates "as-is", also reads them so, but UNIX_TIMESTAMP treats any input dates as in your local timezone and converts them to UTC/GMT timestamps meaning it will apply your local timezone offset, now if you process your timestamps returned from mysql via eg. php date() it will again apply your local timezone offset(note there is also gmtime() which does not do that), which will produce unwanted results.
But you can get by with this following trick which will subtract your session timezone before UNIX_TIMESTAMP() applies it, so you will get the exact number regardless of the server/local timezone if you want the exact same date in db as if it were a GMT time.
mysql> SELECT UNIX_TIMESTAMP(CONVERT_TZ("2013-05-27","GMT",##session.time_zone));
+--------------------------------------------------------------------+
| UNIX_TIMESTAMP(CONVERT_TZ("2013-05-27","GMT",##session.time_zone)) |
+--------------------------------------------------------------------+
| 1369612800 |
+--------------------------------------------------------------------+
1 row in set (0.00 sec)
Another solution would be to set the servers or session timezone to 0(GMT), so there will be no real conversions taking place.
MySQL takes system's default timezone setting unless told otherwise, it explains the problems you are having; take a look at MySQL's time zone reference manual for more details. Based on my past experience I've come to a conclusion UTC is the best choice for storing date and time; when displaying it to the user, they are converted to user's timezone.
If possible, change all date and time entries in the DB to UTC, configure timezone in PHP usingdate_default_timezone_set()and make sure to convert it properly when rendering it to the user and when storing it in the database as well. If storing UTC values is not an option, you may simply convert them by following time zone reference guide the same way as with UTC.
What you need to do is grab raw date and time from the database and then use PHP's DateTime to convert it. Take a look at DateTimeZone as well.
The best that I have found to this problem is using this:
SELECT UNIX_TIMESTAMP(CONVERT_TZ(<<>>,'+15:00','+00:00')) +TIMESTAMPDIFF(second,utc_timestamp(), now())
Example: I want to get the timestamp of 31-may-2012 at 23:59:59, Local time.
SELECT UNIX_TIMESTAMP(CONVERT_TZ('2012-05-31 23:59:59','+15:00','+00:00')) +TIMESTAMPDIFF(second,utc_timestamp(), now())
This way I get the timestamp GMT-0, corresponding to the localtime.
I have found a possible solution which is to just retrieve the date from the database without converting it to Unix time, and then just using strtotime(); to convert it to Unix time. Basically instead of converting using sql, i'm converting using php. The only things I don't like about it are: strtotime() < I'm not sure how reliable this function is, and I have to go and change about 100 places where i'm using UNIX_TIMESTAMP (doh!)
Are there any other ways?

Categories