Here's the scenario - I have the default timezone in PHP set to UTC. All but one date/time that I work with are set to the current UTC time; when displayed later on, I set the timezone for that particular user and the date comes out in their timezone. Works great.
Except I have one date/time that the user can enter on a form. It comes in as "YYYY-MM-DD HH:MM" in 24 hour time (example: "2014-09-18 17:00"). The user is naturally setting this time in their timezone, not UTC.
If I create a new DateTime object with the input value, it saves in UTC, so when displayed later it's off by several hours (depending on the original timezone). If I set the timezone on the new object, it alters the value, assuming, again, that the input value was UTC.
I've done some Googling but have found nothing in regards to PHP (several answers for C# exist that I've found). Is this possible with the DateTime object (or with Carbon)? Am I stuck with doing a manual addition/subtraction of hours based on the users current timezone to place it in UTC first?
You must set timezone when creating DateTime object, and not when it is already created; then change DateTime object to UTC timezone and save it to you db:
# create DateTime based on user timezone
$dt = new DateTime('2014-09-18 17:00', new DateTimezone('Australia/Sydney'));
# change time to UTC timezone
$dt->setTimezone(new DateTimezone('UTC'));
Related
Right now my Laravel application save() any items into the database base on this timestamp. America/New_York because I configured it as 'timezone' => 'America/New_York', in config/app.php.
Goal
I wish to overwrite timestamp based on other tz instead, ex. America/Chicago
How do I do that?
You don't need too
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.)
see https://dev.mysql.com/doc/refman/5.7/en/datetime.html
So when you change the server to another timezone all timestamps will get the new time zone
setting the time zone goe like
SET GLOBAL time_zone = 'America/Chicago';
You don't have to do crazy stuff... What you have to do is:
Store the time in a known timezone and never change that timezone again, it would be awesome if you use UTC as a default timezone.
When you want to "convert" a timezone, you just $model->created_at (or anything that is a Carbon object) and do $model->created_at->setTimezone('America/Chicago'); (for example).
The main idea is that when you already have a Carbon instance with a timestamp, you just change the timezone with setTimezone to the new one you want and it will return a new Carbon instance with that timezone...
Have a look at this SO topic.
Also, remember that timestamp is just an integer representing how many seconds have passed since 1970-01-01 00:00:01 (UTC), so if you say "give me a timestamp of a specific date and time on specific timezone" the timestamp will be always the same even if you change the timezone each time... that is the main idea of the timestamp...
If I say "What timestamp is for 1970-01-01 00:00:10?", if you are on UTC you would get 10, because 10 seconds passed since that specific datetime, if you are on UTC+1, it would still be 10 seconds, but you will display 1970-01-01 00:01:10, because you are 1 hour ahead of UTC, if you are on UTC-1 it will be 1969-12-31 23:00:10, because you are 1 hour behind UTC, but you know how to do the conversion, that is why the value will be always the same disregarding the timezone, and that is also why it is 1970-01-01 00:00:00 and not any other specific datetime, because if you do not know which is the specific datetime you would not know how to do the conversion.
It is very important that you understand what you are working with, so to help you understand better, have a look at this blog explaining the same thing but in more detail.
The timestamp generated in PHP is in UTC time regardless of your local timezone setting.
You can adjust the timezone of the timestamp before it is displayed in the UI using setTimezone.
Reference:
https://www.php.net/manual/en/function.time.php
https://www.php.net/manual/en/datetime.gettimestamp.php
Im have a field with date time type. I see in database is always saved other timezone than my default.
When node content is rendered, date looks fine, but when i trying to get node from code i cant render date in correct timezone.
$node->field_customtime->getValue()
I have array of values with standard timezone, when i dump value, the time is wrong.
So i was trying to do it like that:
$value = $node->field_customtime->getValue();
$value = $value[0]['value'];
$date = new \DateTime($value);
$date = $date->getTimestamp();
echo \Drupal::service('date.formatter')->format($date);
And there is still raw date from database (wrong).
I dont know how to correct display date from custom date field. I see in the form correct date (i.e. 11:00 european time) but in database is 10:00. On node page is correct 11:00 so drupal convert it somehow, but how??
I will assume you are using MySQL?
If so then unless you are saving a timestamp the timezone does not matter. It should be saved exactly how you sent it.
If it is a timestamp then the date is automatically converted into UTC for storage and then converted back into whatever timezone you have set in the mysql configuration.
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.)
What you need to check first is how you are saving the date. Are you storing a timestamp?
If not you need to check how the data is saved and see if anything is happening to the date before inserted into the database.
Unfortunately I do not know much about Drupal but after a quick google I have found out that Drupal 7 happens to have a few ways of handling the datetime. It is quite possible that this may apply for Drupal 8 and you simply need to adjust a configuration.
https://drupal.stackexchange.com/questions/3613/the-differences-between-date-time-zone-handling
I'm working on something where the user can select their own timezone and the software will be able to be used by others on their sites as well but I want to make sure that the timezone within the database is always set to UTC.
Now I know how you set the default timezone for PHP, such as:
date_default_timezone_set('Australia/Sydney');
...but I'm not sure how to make sure MySQL is using UTC? ...and even once you have made sure it is using UTC I guess you would have to convert your PHP dates/times into UTC before passing it to the database?
I guess I am wondering about many different date formats such as TIMESTAMP, DATETIME & even UNIX EPOCH integer timestamps which would simply be stored as a int datatype for example.
Then there is the whole retrieving dates/times from the DB and converting it to the respective timezone and lastly how does DST come into all of this?
I know there is a lot of similar questions out there, but I guess none really answered all my questions.
MySQL's data type timestamp stores the dates in UTC. For this to work properly, MySQL uses server's time zone and does the date conversion. It converts the date from servers's current time zone to UTC for storage. This implies that the database server should never change its time zone for this feature to work properly.
When you send the data to such a database, you send the UTC time as well. The easiest way to do this is to format a result of time() according to what MySQL wants (m-d-Y H:i:s).
In PHP, when you format the date for insertion to MySQL, it's the best to use DateTime class. It lets you offset the date with the time zone information, meaning that you don't have to use date_default_timezone_set function - that can lead to mistakes.
An example of DateTime in action:
$date = '1.12.2015 13:37:37'; // Format is day.month.year hour:minute:second
// We create DateTime from custom date format, for the person who resides in Australia/Sydney time zone
$dt = DateTime::createFromFormat('d.m.Y H:i:s', $date, new DateTimeZone('Australia/Sydney');
// Now we change the date's time zone into UTC, and we can insert it into MySQL
$dt->setTimeZone(new DateTimeZone('UTC'));
// This is the formatted date-string that can be safely inserted into MySQL
$date_string_for_mysql = $dt->format('m-d-Y H:i:s');
Alternatively, you can use int type in MySQL for timestamp storage and insert result of time() but this has a huge disadvantage of not being able to use date-related functions.
for current session of mysql you can try something like
SET time_zone = timezonename;
for more details you can also look into this answer https://dba.stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp
I'm currently adding support for internationalisation to a system written in PHP. All dates are now stored as UTC, and displayed according to individual user localisation preferences.
However when a user inputs a date time (such as to specify a certain time window), the date time they input gets interpreted as a UTC datetime, not their local datetime. For the internationalisation to be complete the system needs to assume that a datetime entered by the user refers to their local time.
How do I convert a date string (ie 'YYYY-MM-DD HH:MM') into a unix timestamp for the correct localisation?
Further Clarification -
All dates in database = UTC Timestamps
All HTML Pages display users local time (as defined in their settings)
HTML form has date that defaults to current local time
PHP must treat that date time as local not UTC
PHP must convert this local date timestring into UTC timestamp
Assuming you know the timezone of the user, which he presumably chose in the preferences somewhere:
$timezone = new DateTimeZone($usersTimezone);
$datetime = new DateTime('2012-01-18 20:00:00', $timezone);
echo $datetime->getTimestamp();
This requires a recent version of PHP with DateTime.
date_default_timezone_set("Asia/Singapore"); // UTC +8
$dt = new DateTime();
$dt->setTimestamp(DateTime::createFromFormat('u', gmdate('u'))->getTimestamp());
echo $dt->getTimezone()->getName(); // Asia/Singapore
echo $dt->format('d M Y H:i:s'); // Correct local time
$dt->setTimezone(new DateTimeZone('UTC'));
echo $dt->format('d M Y H:i:s'); // Correct UTC Time
die;
I am wondering if timestamps contain timezone data. On line 3 you see that I used gmdate() which should give me UTC/GMT time. But when I get the timezone & formatted datetime, they are in localtime. I didn't set timezones in my DateTime object yet, gave it a UTC timestamp. It somehow knew to convert to localtime. Which makes me wonder if Timezone data are included in timestamps
setTimestamp accepts the timestamp in GMT 0 and you passed it in GMT, because of gmdate('u'). DateTime object takes your current timezone by default.
After that - you have properly set timestamp and current timezone, that is why DateTime object formats the date for Singapore.
Which makes me wonder if Timezone data are included in timestamps
No. Timestamp stores just amount of seconds since unix-epoch.
Timestamps are interpreted according to the interpreters timezone.
So no, they are standard and do not contain timezone data within themselves.
your example proves it, as you change the timezone, so does your result.
If the timezone data was embedded, the result would not change.