I have unix timestamps created in a database table. I know user's timezone it is also saved in a table and int the format of "GMT+04:00" , "GMT+05:30"
What I'm trying to do is take the timestamp and show readable time to the users according to their timezone.
Ex.
$startTime = '1524391500';
echo date('h:ia', $startTime) . '<br>';
date_default_timezone_set('America/Fortaleza');
echo date('h:ia', $startTime) . '<br>';
this will give us the result
10:05am
07:05am
The problem is date_default_timezone_set doesn't accept the timezone in this
date_default_timezone_set('GMT+05:30');
So I need a way to convert "GMT+05:30" to something like "America/Fortaleza"
can some one help me with this?
What you ask for is not possible. A time zone and a time zone offset are two different things.
Consider a single time zone like America/Sao_Paulo. It uses an offset of -03:00 during Standard Time, and an offset of -02:00 during Daylight Saving Time.
Now consider that America/Fortaleza you mentioned uses -03:00 over the entire year.
As you can see, for a given time zone I may have more than one offset, and for a given offset I may have more than one time zone. You can review the lists of time zones and their offsets if you want to find more examples for yourself.
This is covered extensively in other answers, as well as in the "Time Zone != Offset" section of the timezone tag wiki.
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.
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.
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
I have a date string, say '2008-09-11'. I want to get a timestamp out of this, but I need to specify a timezone dynamically (rather then PHP default).
So to recap, I have two strings:
$dateStr = '2008-09-11';
$timezone = 'Americas/New_York';
How do I get the timestamp for this?
EDIT: The time of day will be the midnight of that day.... $dateStr = '2008-09-11 00:00:00';
$date = new DateTime($dateStr, new DateTimeZone($timezone));
$timestamp = $date->format('U');
The accepted answer is great if you're running PHP > 5.2 (I think that's the version they added the DateTime class). If you want to support an older version, you don't want to type as much, or if you just prefer the functional approach there is another way which also does not modify global settings:
$dateStr = '2008-09-11 00:00:00';
$timezone = 'America/New_York';
$dtUtcDate = strtotime($dateStr. ' '. $timezone);
This will work if for some reason you're using <5.2 (Heaven forbid).
$reset = date_default_timezone_get();
date_default_timezone_set('America/New_York');
$stamp = strtotime($dateStr);
date_default_timezone_set($reset);
But anything 5.2 and above, I'd strongly recommend you opt for #salathe's answer.
If you're going to use Timezones, I propose you use the DateTime class, and in this case the DateTime::createFromFormat() function which will allow you to do something like this:
$start = "2015-01-14 11:59:43";
$timezone = "America/Montreal";
$tz = new DateTimeZone($timezone);
$dt = DateTime::createFromFormat('Y-m-d H:i:s', $start, $tz);
When you put $tz in the DateTime::createFromFormat function, you tell it what time zone the date you gave is in, so that when you need to convert it to another timezone, all you have to do is something like this:
$start = $dt->setTimeZone(new DateTimeZone('UTC'));
Whenever you are referring to an exact moment in time, persist the time according to a unified standard that is not affected by daylight savings. (GMT and UTC are equivalent with this regard, but it is preferred to use the term UTC. Notice that UTC is also known as Zulu or Z time.)
If instead you choose to persist a time using a local time value, include the local time offset from UTC, such that the timestamp can later be interpreted unambiguously.
In some cases, you may need to store both the UTC time and the equivalent local time. Often this is done with two separate fields, but some platforms support a datetimeoffset type that can store both in a single field.
When storing timestamps as a numeric value, use Unix time - which is the number of whole seconds since 1970-01-01T00:00:00Z (excluding leap seconds). If you require higher precision, use milliseconds instead. This value should always be based on UTC, without any time zone adjustment.
If you might later need to modify the timestamp, include the original time zone ID so you can determine if the offset may have changed from the original value recorded.
When scheduling future events, usually local time is preferred instead of UTC, as it is common for the offset to change. See answer, and blog post.
Remember that time zone offsets are not always an integer number of hours (for example, Indian Standard Time is UTC+05:30, and Nepal uses UTC+05:45).
If using Java, use java.time for Java 8, or use Joda Time for Java 7 or lower.
If using .NET, consider using Noda Time.
If using .NET without Noda Time, consider that DateTimeOffset is often a better choice than DateTime.
If using Perl, use DateTime.
If using Python, use pytz or dateutil.
If using JavaScript, use moment.js with the moment-timezone extension.
If using PHP > 5.2, use the native time zones conversions provided by DateTime, and DateTimeZone classes. Be careful when using.
DateTimeZone::listAbbreviations() - see answer. To keep PHP with up to date Olson data, install periodically the timezonedb PECL package; see answer.
If using C++, be sure to use a library that uses the properly implements the IANA timezone database. These include cctz, ICU, and Howard Hinnant's "tz" library.
Do not use Boost for time zone conversions. While its API claims to support standard IANA (aka "zoneinfo") identifiers, it crudely maps them to fixed offsets without considering the rich history of changes each zone may have had.
(Also, the file has fallen out of maintenance.)
Most business rules use civil time, rather than UTC or GMT. Therefore, plan to convert UTC timestamps to a local time zone before applying application logic.
Remember that time zones and offsets are not fixed and may change. For instance, historically US and UK used the same dates to 'spring forward' and 'fall back'.
However, in 2007 the US changed the dates that the clocks get changed on. This now means that for 48 weeks of the year the difference between London time and New York time is 5 hours and for 4 weeks (3 in the spring, 1 in the autumn) it is 4 hours. Be aware of items like this in any calculations that involve multiple zones.
Consider the type of time (actual event time, broadcast time, relative time, historical time, recurring time) what elements (timestamp, time zone offset and time zone name) you need to store for correct retrieval - see "Types of Time" in answer.
Keep your OS, database and application tzdata files in sync, between themselves and the rest of the world.
On servers, set hardware clocks and OS clocks to UTC rather than a local time zone.
Regardless of the previous bullet point, server-side code, including web sites, should never expect the local time zone of the server to be anything in particular. see answer.
Use NTP services on all servers.
If using FAT32, remember that timestamps are stored in local time, not UTC.
When dealing with recurring events (weekly TV show, for example), remember that the time changes with DST and will be different across time zones.
Always query date-time values as lower-bound inclusive, upper-bound exclusive (>=, <).
Laconic Answer (no need to change default timezone)
$dateStr = '2008-09-11';
$timezone = 'America/New_York';
$time = strtotime(
$dateStr,
// convert timezone to offset seconds
(new \DateTimeZone($timezone))->getOffset(new \DateTime) - (new \DateTimeZone(date_default_timezone_get()))->getOffset(new \DateTime) . ' seconds'
);
Loquacious Answer
Use strtotime's second option which changes the frame of reference of the function. By the way I prefer not to update the default time zone of the script:
http://php.net/manual/en/function.strtotime.php
int strtotime ( string $time [, int $now = time() ] )
The function
expects to be given a string containing an English date format and
will try to parse that format into a Unix timestamp (the number of
seconds since January 1 1970 00:00:00 UTC), relative to the timestamp
given in now, or the current time if now is not supplied.
And a Helper
/**
* Returns the timestamp of the provided time string using a specific timezone as the reference
*
* #param string $str
* #param string $timezone
* #return int number of the seconds
*/
function strtotimetz($str, $timezone)
{
return strtotime(
$str, strtotime(
// convert timezone to offset seconds
(new \DateTimeZone($timezone))->getOffset(new \DateTime) - (new \DateTimeZone(date_default_timezone_get()))->getOffset(new \DateTime) . ' seconds'
)
);
}
var_export(
date(
'Y-m-d',
strtotimetz('this monday', 'America/New_York')
)
);
Maybe not the most performant approach, but works well when you know the default timezone and the offset. For example if the default timezone is UTC and the offset is -8 hours:
var_dump(
date(
'Y-m-d',
strtotime('this tuesday', strtotime(-8 . ' hours'))
)
);