Background: I have some PHP code that calculates the next time a recurring message should be sent according to various rules. I also have a sanity page that double checks that the next recurrence is correct. Due to a timezone problem that I am not sure how to resolve, the sanity page is showing some problems that I am not sure if they are actually problems.
I believe that these are showing up because the (future) date is during BST (British Summertime) but the Europe/London timezone is currently on GMT.
I created a very simplified test page to debug and test one example. The code is as follows:
// Not included: DB connection setup, which includes a query to set the MySQL session timezone to the current timezone for Europe/London as calculated by PHP
// Copied from a comment at http://php.net/manual/en/function.date-default-timezone-get.php
function timezone_offset_string( $offset )
{
return sprintf( "%s%02d:%02d", ( $offset >= 0 ) ? '+' : '-', abs( $offset / 3600 ), abs( $offset % 3600 ) );
}
$offset = timezone_offset_get( new DateTimeZone( date_default_timezone_get() ), new DateTime() );
// query_multiple() is a function to get a single result from the database and return it as the specified PDO type
$db = query_multiple("SELECT NextRecurrence, UNIX_TIMESTAMP(NextRecurrence) AS NextTS, IF(##session.time_zone = 'SYSTEM', ##system_time_zone, ##session.time_zone) AS DBTZ FROM RecurringMessages WHERE RecurID=96 LIMIT 1", "", "", PDO::FETCH_ASSOC);
print "DB Date of NextRecurrence : ".$db['NextRecurrence']."<br>";
print "DB timestamp of NextRecurrence : ".$db['NextTS']."<br>";
print "DB timezone : ".$db['DBTZ']."<br>";
print "PHP timezone and offset: " .date_default_timezone_get().", ".timezone_offset_string( $offset ) . "<br>";
print "PHP date of NextTS : ".date('Y-m-d H:i:s', $db['NextTS'])."<br>";
The output of this page is as follows:
DB Date of NextRecurrence : 2017-05-24 10:00:00
DB timestamp of NextRecurrence : 1495620000
DB timezone : +00:00
PHP timezone and offset: Europe/London, +00:00
PHP date of NextTS : 2017-05-24 11:00:00
As you can see, the PHP date is one hour different, even though the PHP and MySQL timezones are the same. As mentioned above, I believe that this is because the date given is during BST and Europe/London is currently GMT.
If I put 1495620000 into http://www.epochconverter.com/, it tells me that it is Wed, 24 May 2017 10:00:00 GMT
There are two things that I am currently unsure of
Is the current database entry correct? When it comes to May 24th 2017, will this message be sent at 10:00 or 11:00? The PHP code, which is used for sending the message, sets the session time zone for MySQL right after connecting to match the current timezone for Europe/London.
If the database entry is correct, how do I get the PHP date function to give me the correct output for any future date? If the PHP date function is correct, how do I (generically) update the MySQL record with the correct date? All I know is that it should be sent on May 24th 2017 at 10:00. Currently the query updates with UPDATE SET NextRecurrence='2017-05-24 10:00:00' ...
I figured it out (I think).
Because MySQL is currently at GMT, I need to present the Y-m-d H:i:s formatted date and time to MySQL in GMT, even if the date is during BST.
// $ts contains the correct unix timestamp
$offsetnow=date('Z');
$tsoffset=date('Z', $ts);
$diff=$offsetnow-$tsoffset;
// Add the difference to the timestamp so that the PHP date returns the appropriately presented Y-m-d H:i:s to MySQL, which as of writing this is GMT.
$ts+=$diff;
$query="UPDATE Recurrences SET NextRecurrence='".date('Y-m-d H:i:s', $ts)."' ...
If anyone sees a mistake in what I am doing, please let me know!
Related
Environment: Wordpress, XAMPP Version: 7.2.10, PHP 7.2, Windows 10
I am calculating a user subscription expiration date (by adding 90 days to today's date) and storing it in a mysql database. Although the php calculation shows the date in the right timezone, the date stored in the MySQL table is incorrect by +5 hours. For example, "2019-10-29 14:55:01" should be "2019-10-29 9:55:01". (FYI - other timestamp fields that have an "on update CURRENT_TIMESTAMP" attribute are updating to the correct timezone. Also the Windows environment is set correctly.)
I have tried the following with no success:
setting the default timezone in my php code.
adding the following to my .htaccess: php_value date.timezone 'America/Chicago'
php_value date.timezone 'America/Chicago'
adding this to php.ini: date.timezone=America/Chicago
(Restarting Xampp after each change.)
My PHP Code:
$start_date = date("Y-m-d H:i:s"); // Today's date in timestamp format.
$default_subscription_period = get_option('apr2s_user_subscription_period' ); // For now, 90 days
$user_subscription_expire_date = calculate_user_subscription_expire_date($start_date, $default_subscription_period);
echo "Start Date is : ".$start_date."<br>"; // Shows correct date & time in correct timezone
echo "Expire Date is : ".$user_subscription_expire_date."<br>"; // Shows correct date & time in correct timezone
$results1 = $wpdb->insert($user_table_name, array(
"user_subscription_expire_date" => $user_subscription_expire_date,));
function calculate_user_subscription_expire_date($start_date, $subscription_period_in_days){
date_default_timezone_set('America/Chicago');
$expire_date = date('Y-m-d H:i:s', strtotime($start_date. ' + '.$subscription_period_in_days.'days'));
return ($expire_date);
}
Ideas? Thanx!
You should store everything in UTC for simplicity. Perform all calculations in UTC too. Convert into the right timezone only when displaying to the user, and use DateTime() class to do so instead of date_default_timezone_set. It is best to keep your default timezone set to UTC in PHP and MySQL.
You could avoid making the date calculation in PHP altogether and use SQL functions.
INSERT INTO $user_table_name (user_subscription_expire_date)
VALUES (DATE_ADD(NOW(), INTERVAL 90 DAY))
or dynamically in wordpress:
$wpdb->query( $wpdb->prepare("INSERT INTO $user_table_name (user_subscription_expire_date)
VALUES (DATE_ADD(NOW(), INTERVAL %d DAY))",
$default_subscription_period
) );
When you want to display to the user just use:
$date = new \DateTime($dateFromDB);
$date->setTimezone(new \DateTimeZone('America/Chicago'));
I am encountering a slightly frustrating problem and I have a feeling there is a simple solution to it. When I pass the same UNIX timestamp to the PHP date and MySQL FROM_UNIXTIME methods they are returning two very different dates. I would like to return a value from MySQL that matches the one returned by PHP.
Here is the code I am currently using along with it's output. The timestamp provided represents the date Tue, 01 Jan 2013 (01/01/2013). Also for reference, here are the format values.
MySQL Format
%j = Day of year (001..366).
%m = Month, numeric (00..12).
%y = Year, numeric (two digits).
PHP Format
z = The day of the year starting from 0 (0 through 365).
m = Numeric representation of a month, with leading zeros (01 through 12).
y = A two digit representation of a year (Examples: 99 or 03).
MySQL Query
SELECT FROM_UNIXTIME(1357018200, '%j-%m-%y');
-> 366-12-12
PHP Code
echo date('z-m-y', 1357018200);
-> 0-01-13
Any help would be greatly appreciated, thanks for your time. :)
Other Information
MySQL Version: 5.5.23
MySQL system_time_zone: CDT
MySQL time_zone: SYSTEM
PHP date_default_timezone_get: America/Chicago (CDT)
Your PHP and MySQL aren't agreeing on the time. Using the time converter at:
http://www.4webhelp.net/us/timestamp.php?action=stamp&stamp=1357018200&timezone=-6
gives the result "Monday, December 31st 2012, 23:30:00 (GMT -6)" so your PHP is giving the wrong result. Although you've given the timezone that PHP is running in, can you double check by running:
date_default_timezone_set ("America/Chicago");
echo date('z-m-y', 1357018200)."\r\n";
Which should give "365-12-12".
I guess it's possible either something is setting the timezone incorrectly somewhere else or possibly that "America/Chicago (CDT)" is an old setting in your php.ini file from a previous version of PHP.
Looking at the list of allowed timezone values from http://php.net/manual/en/timezones.america.php there is no "America/Chicago (CDT)" listed, so you should figure out where it's getting set to that bogus value as it may cause other issues.
Once you've got your timezone issues sorted out, the answer to your actual question is:
function sqlStyleDate($timestamp){
$dayOfYear = date("z", $timestamp) + 1;
$year = date("y", $timestamp);
$month = date("n", $timestamp);
$result = "$dayOfYear-$year-$month";
return $result;
}
echo sqlStyleDate(1357018200)."\r\n";
That will convert PHPs 0-365 day of year, to be the same as MySQL's 1-366 day of year.
This is my current code that doesn't seem to work correctly.
echo date("h:i", 1*60*60) ; /* 1*60*60 mean 1 hours right */
The result is 03:00 when it should be 01:00.
Where is this going wrong?
i want to do this
1- employee come in time admin select it
2- employee come - leave saved in mysql as timestamp
Now I'm trying to make admin see how many hours user late
mean
user date time default late
user1 11-09-2011 09:10 09:00 10 min
user1 12-09-2011 08:00 09:00 -60 min
If you output just date("Y-m-d H:i:s",0) you should see that it's not 1970-01-01 00:00:00 as it should be. It's because date is affected by your local timezone. For example I'm in GMT +3, and date("Y-m-d H:i:s") gives me 1970-01-01 03:00:00.
So the answer is you are not in GMT timezone (probably in GMT+2), and date is affected by it.
UPDATE
The following code outputs 1970-01-01 00:00:00, so it's definitely time zones.
date_default_timezone_set('UTC');
echo date("Y-m-d H:i:s", 0);
Hovewer, I can't see any mention about it in PHP's date manual.
The problem is due to your timezone (looks like GMT+2).
Date calculations in PHP are based on the configured server timezone. For example mine shows
$ php -r 'echo date("h:i", 3600), PHP_EOL;'
11:00
The second argument in date() function must be UNIX timestamp, seconds passed from Jan 1 1970. You need to make time according to that value.
You have probably not setup time zones, which should produce a PHP warning or notice if omitted.
It occurs to me that what SamarLover think he wants is
gmdate("h:i", 1 * 60 * 60);
Err, if I'm right, date()'s second param is a unix timestamp, so the seconds since 1970.
You have to get time() and add 60*60 to it.
echo date("h:i", time()+60*60); // get current timestamp, add one hour
I have a mySQL database with a timestamp field. It currently only has one entry while I'm testing, it is
2010-02-20 13:14:09
I am pulling from the database and using
echo date("m-d-Y",$r['newsDate'])
My end result is showing as
12-31-69
Anyone know why?
Edit:
editedit:
disregard that edit... the FTP addon for notepad++ timed out and unfortunately doesn't display an error when it can't synch.
The date function expects an UNIX timestamp as its second parameter -- which means you have to convert the date you get from the DB to an UNIX timestamp, which can be done using strtotime :
$db = '2010-02-20 13:14:09';
$timestamp = strtotime($db);
echo date("m-d-Y", $timestamp);
And you'll get :
02-20-2010
You were passing the '2010-02-20 13:14:09' string to the date function ; that string is not a valid UNIX Timestamp.
'12-31-69' is probably 1970-01-01, in your locale ; and 1970-01-01 is the Epoch -- the date that corresponds to the 0 UNIX Timestamp.
For starters, the php date() function is expecting seconds as the second variable. So that accounts for why your date is displaying wrong. Check this source on that issue.
Which then provides us the answer to the problem, to get PHP to format the date from a SQL timestamp correctly, we just change the query a tad...
SELECT author, `when`
Change it to...
SELECT author, UNIX_TIMESTAMP(`when`)
Then use the PHP date function, with the variable that is storing the result of that above SQL query.
You could just use MySQL's date_format() function instead:
SELECT date_format(timestampfield, '%m-%d-%Y') FROM table etc....
This will save you having to round-trip your timestamp into unix time and then back into a normal date string in PHP. One datetime formatting call rather than two.
i think this will be useful to newble:
example basic subtraction 1 hour from date from MYSQL format:
$to='2013-25-10 22:56:00'; //curr time
$timestamp = strtotime($to); //convert to Unix timestamp
$timestamp = $timestamp-3600; //subtract 1 hour (3600 this is 1 hour in seconds)
echo date("Y-m-d H:i:s",$timestamp); //show new date
EDIT: After checking, it appears that MySQL returns a timestamp as a string to PHP, so this answer was bogus :)
Anyway, the reason you get a date in 1969 is probably that you're converting a zero unix time from UTC to localtime. The unix time is the number of seconds since 1970. So a value of 0 means 1970. You probaby live in a timezone with a negative offset, like GMT-6, which ends up being 31-12-69.
ok, I was wrestling with this for a week (longer but i took a break from it).
I have two specific fields in tables
creationDate > timestamp > current_timestamp
editDate > timestamp > current_timestamp
they were pulling out either dec 31 1969, or just nothing... annoying... very annoying
in mysql query i did:
unix_timestamp(creationDate) AS creationDate
unix_timestamp(editDate) AS editDate
in php convert i did:
$timestamp = $result_ar['creationDate'];
$creationDate = date("Y-M-d (g:i:s a)", $timestamp)
echo($creationDate);
$editstamp = $result_ar['editDate'];
$editDate = date("Y-M-d (g:i:s a)", $editstamp)
echo($editDate);
this solved my problem for me returning
2010-Jun-28 (5:33:39 pm)
2010-Jun-28 (12:09:46 pm)
respectively.
I hope this helps someone out..
I've found many examples about UTC tables and php date methods to convert it, but I still miss a simple way after got server date, to converting it into an user timezone selection on my web page.
On this page http://vkham.com/UTC.html I've found a clear guide to understand the range, but I don't know how to connect for example "Europe/Rome" on the table, so there is something more clear about it?
I know the timezone of my server (America/Chicago) but I still don't know a way to change it from UTC method to a different timezone selected from the user machine (for example "Europe/Rome")
I tryied something, but I'still miss something, and i don't know what is it:
<?php
$timezone = date ("e");
$date = date ('Y-m-d H:i:s');
print $date." - this is my server date, and his timezone is - $timezone<br/>";
$user_timezone = "Europe/Rome"; // there is a way to convert Europe/Rome to UTC -13?
$selected_timezone = "-13"; // is -13 like Europe/Rome in all cases or only because my server is America/Chicago?
$date_user = date ("Y-m-d H:i:s $selected_timezone");
$str_date_user = strtotime ($date_user);
$new_user_date = date ('Y-m-d H:i:s', $str_date_user);
print $new_user_date . " - this is my server date, and his timezone is - $user_timezone";
?>
Doesn't exist a way to convert Europe/Rome to -13 for UTC timezone?
Is -13 like Europe/Rome in all cases or only because my server is America/Chicago?
You can use gmdate to generate a date that is displaying the UTC time - whatever timezone your server is running in. Then you can simply add the timezone difference as hours * 3600 to the timestamp you use for generating the date to get the user's time.
A different way would be setting the local time temporary to the user's timezone by using date_default_timezone_set.
A simple example for the first idea would be the following:
<?php
$offset = -13 * 3600; // timezone offset for UTC-13
$utcTime = gmdate( 'd.m.Y H:i' );
$userTime = gmdate( 'd.m.Y H:i', time() + $offset );
?>