开发者

php: setting a timezone by UTC offset

Using javascript I know that my users timezone is UTC +3.

Now I want to create DateTime object with this knowledge:

$usersNow = new DateTime('now', new DateTimeZone("+3"));

I receive as a开发者_Go百科 respsonse:

'Unknown or bad timezone (+2)'

What am I doing wrong? How can I fix?


how about this...

$original = new DateTime("now", new DateTimeZone('UTC'));
$timezoneName = timezone_name_from_abbr("", 3*3600, false);
$modified = $original->setTimezone(new DateTimezone($timezoneName));


You said:

Using javascript I know that my users timezone is UTC +3.

You probably ran something like this:

var offset = new Date().getTimezoneOffset();

This returns the current offset from UTC in minutes, with positive values falling west of UTC. It does not return a time zone!

A time zone is not an offset. A time zone has an offset. It can have multiple different offsets. Often there are two offsets, one for standard time and one for daylight saving time. A single numeric value cannot represent this alone.

  • Example of a time zone: "America/New_York"
    • Corresponding standard offset: UTC-5
    • Corresponding daylight offset: UTC-4

Besides the two offsets, also wrapped up in that time zone are the dates and times for transitioning between the two offsets so you know when they apply. There's also a historical record of how the offsets and transitions may have changed over time.

See also "Time Zone != Offset" in the timezone tag wiki.

In your example case, you probably received a value of -180 from javascript, representing a current offset of UTC+3. But that's just the offset for that particular point in time! If you follow minaz's answer, you will get a time zone that makes the assumption that UTC+3 is always the correct offset. That would work if the real time zone is something like "Africa/Nairobi" which has never used anything except UTC+3. But for all you know your user could be in "Europe/Istanbul", which uses UTC+3 in the summer and UTC+2 in the winter.


Modern answer:

$usersNow = new DateTime('now', new DateTimeZone('+0300'));

Documentation:

http://php.net/manual/en/datetimezone.construct.php


Since PHP 5.5.10, DateTimeZone accepts an offset like "+3" :

https://3v4l.org/NUGSv


This one takes Matthew's answer a step further to change the timezone of a date to any integer offset.

public static function applyHourOffset(DateTime $dateTime, int $hourOffset):DateTime
{
    $dateWithTimezone = clone $dateTime;

    $sign = $hourOffset < 0 ? '-' : '+';
    $timezone = new DateTimeZone($sign . abs($hourOffset));
    $dateWithTimezone->setTimezone($timezone);

    return $dateWithTimezone;
}

Note: I had a breakage in production due to the accepted answer.


As far as I can tell from the docs on DateTimeZone, you need to pass a valid time zone and here are the valid ones. Check the others, something there may help you.


DateTimeZone requires a timezone not an offest


did you try this

http://php.net/manual/en/function.strtotime.php

 <?php
    echo strtotime("now"), "\n";
    echo strtotime("10 September 2000"), "\n";
     echo strtotime("+5 hours");
    echo strtotime("+1 day"), "\n";
    echo strtotime("+1 week"), "\n";
    echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";
    echo strtotime("next Thursday"), "\n";
    echo strtotime("last Monday"), "\n";
    ?>


For anyone who comes across this, I was facing the same problem, so in the end I extended the DateTime class and overrode the __construct() method to accept an offset (in minutes) instead of a timezone.

From there, my custom __construct() works out what the offset is in hours and minutes (e.g. -660 = +11:00) and then uses parent::__construct() to hand my date, custom formatted to include my offset, back to the original DateTime.

Because I'm always dealing with UTC times in my application, my class also modifies the UTC time by subtracting the offset, so passing Midnight UTC and an offset of -660 will show me 11am

My solution is detailed here: https://stackoverflow.com/a/35916440/2301484


I was directed to a solution thanks to Joey Rivera's link. Like what the others have said here, timezone is not an offset you do need a valid timezone.

This is what I am using for myself

$singapore_time = new DateTime("now", new DateTimeZone('Asia/Singapore'));


var_dump( $singapore_time );

I myself have found it to be much more convenient to work with YYYY-MM-DD HH:MM format. example.

$original = new DateTime("2017-05-29 13:14", new DateTimeZone('Asia/Singapore'));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜