Converting to the same timezone in php - php

Strangeness. It's not an edge case. Rather, let's say my server stores it's date/time in America/Toronto. I then run the it through time conversion logic incase, say, you're on the west coast. Here's the code I got:
$timestamp = '2012-07-25 16:30:00';
$to = 'America/Toronto';
$from = 'America/Toronto';
// system timezone
$system = (new DateTimeZone($from));
// desired conversion timezone
$desired = (new DateTimeZone($to));
// timestamp DateTime object
$resource = (new DateTime($timestamp, $system));
// offset
$offset = $desired->getOffset($resource);
print($offset);
The offset that is getting printed at this point is -14440 (4 hours). I don't imagine the system or database timezones are coming in here (both of which are set to America/Toronto). Any light would be appreciated on this. Confusing :(

DateTimeZone::getOffset() returns the offset in seconds from GMT (-14440 = 4 hours for America/Toronto).
Edit:
Apologies for my initial confusion with DateTime::getOffset()!
Anyway, to address the title of your question, use DateTime::setTimeZone() to convert between timezones.

This is probably what you're looking for, the offset between the 2 timezones.
// system timezone
$system = (new DateTimeZone($from));
// desired conversion timezone
$desired = (new DateTimeZone($to));
// timestamp DateTime object
$resource = (new DateTime($timestamp, $system));
$desiredDateTime = (new DateTime($timestamp, $desired));
// offset
$offset = $desired->getOffset($desiredDateTime) - $system->getOffset($resource);
print($offset);

Related

Timezone Format without colon

I am trying to get the timezone format to just show -6 rather than -06:00 but can't figure this out.
My current code outputs the format (since I am in central time) as -21600
SO I am trying to convert this using the following...
$time_offset_get = new \DateTime('now', new DateTimeZone(America/Chicago));
$conn_timezone_offset = $time_offset_get->format('P');
But of course, this ($conn_timezone_offset) is giving me -06:00
Is there another format code that will do this correctly or am I am doing this wrong altogether.
Overall, I am just trying to convert a timezone offset name like America/Chicago or a 3 digit timezone code into a number offset without the colon using PHP.
Use DateTime::getOffset
Returns the timezone offset in seconds from UTC on success or FALSE on
failure.
To get the offset in hours, simply divide the value by 3600.
$now = new \DateTime('now', new DateTimeZone('America/Chicago'));
$offset = $now->getOffset();
if ($offset !== false) {
$offset = round($offset / 3600);
} else {
// the error handling here
}

Laravel 5.3 - Carbon Date - UTC offset get timezone name

I am trying to get a timezone name from a UTC offset in Laravel 5.3 using Carbon. Code listed below any help would be much appreciated.
/* current code iteration */
$utcOffset = -5;
$timezone = Carbon::now($utcOffset)->timezone->getName();
echo $timezone;
// Result: -05:00
// Expected Result: EST
/* tried code */
$timezone = Carbon::now($utcOffset)->tzName;
// Result: -05:00
/* What I used prior to Carbon */
$timezone = timezone_name_from_abbr(null, $utcOffset * 3600, TRUE);
$dateTime = new DateTime();
$dateTime->setTimeZone(new DateTimeZone($timezone));
$timezone = $dateTime->format('T');'
What am I missing? I feel daft..
Preface:
The accepted answer works in most cases but as mentioned in the user contributed notes area of timezone_name_from_abbr(), there are issues with using the function, like returning false instead of actual timezone and returning a "historical" (i.e. deprecated) timezone identifier rather than the current standard one for a given location. Which are still valid to this date.
Also, the original code returns the value as expected, as long as you know that as per Carbon docs, if you look at https://carbon.nesbot.com/docs/#api-timezone
the original name of the timezone (can be region name or offset string):
One more thing to note here is that, it is considered not reliable to derive timezone off of offset value as it does not take into consideration the DST observed periods offset.
So, this all to actually say that deriving timezone off of offset is not always possible.
Answer:
But since the OP mentioned Carbon and timezone based on offset, as per the Carbon docs as of now, the answer should be
$date = Carbon::now('-5');
echo $date->tzName;
Tried updating Carbon to no evail ended up using the old datetime class.
$timezone = timezone_name_from_abbr(null, $utcOffset * 3600, TRUE);
$dateTime = new DateTime();
$dateTime->setTimeZone(new DateTimeZone($timezone));
$timezone = $dateTime->format('T');
In a new Carbon it is timezoneName property;
$now = Carbon::now(-5);
echo $now->timezoneName;
//or
echo $now->timezone->getName();
This works for me:
$now = Carbon::now(-5);
echo $now->timezone;
// prints 'America/Chicago'

Convert timezone offset to hours & minutes preserving sign

Suppose I have an offset like this:
$secOffset = -28800
I need it to convert in a format that is usable with MYSQL function convert_tz()
If I use gmdate("h:i", secOffset) I got 16:00 that is almost correct but It miss the minus - (that is quite important)
Alternative approach:
Suppose I have a time string America/Los_Angeles and I want to convert in a offset useful for MYSQL function convert_tz()
The final expected output is the offset from GMT so given a timezone.
For ex, having a timezone like America/Los_Angeles, the output should be:
−08:00
I'm on Magento/Zend so if any available function is on Zend I can accept answer based on it.
You should use the DateTimeZone and DateInterval classes for this:
$tzid = 'America/Los_Angeles';
$tz = new DateTimeZone($tzid);
$date = new DateTime('now', $tz);
// create a new date offset by the timezone offset
// gets the interval as hours & minutes
$offset = $tz->getOffset($date) . ' seconds';
$dateOffset = clone $date;
$dateOffset->sub(DateInterval::createFromDateString($offset));
$interval = $dateOffset->diff($date);
$formatted = $interval->format('%R%H:%I');
This is a little convoluted, as you first get the timezone offset in seconds, and then use DateTime to help convert that interval into hours/mins.

Converting GMT time to local time using timezone offset in php

I need to display user's activities date as per the current time zone.
My approach -
Getting a timezone offset from javascript and storing it to the user's profile table.
When user logged in, getting time zone offset.
current date is working fine with time zone offset-
$offsetDiff = $_SESSION['TimeZone']*60;
$UserDateTime = time() + $offsetDiff;
$currentDate = date('Y-m-d',$UserDateTime);
Dateo other then today is not working properly -
$offsetDiff = $_SESSION['TimeZone']*60;
$UserDateTime = '2014-02-10 08:58:00'; + $offsetDiff;
$monthUser = date('Y-m-d',$UserDateTime);
Can anybody please let me know how can i show correct date according to time zone offset?
You can convert a specific offset to a DateTimeZone:
$offset = '-0500';
$isDST = 1; // Daylight Saving 1 - on, 0 - off
$timezoneName = timezone_name_from_abbr('', intval($offset, 10) * 36, $isDST);
$timezone = new DateTimeZone($timezoneName);
Then you can use it in a DateTime constructor, e.g.
$datetime = new DateTime('2012-04-21 01:13:30', $timezone);
or with the setter:
$datetime->setTimezone($timezone);
In the latter case, if $datetime was constructed with a different timezone, the date/time will be converted to specified timezone.

PHP: Why is this code erroneously returning zero?

I'm calculating the offset between two timezones, but I'm seeing a result I don't expect (zero) with the following code:
$datetimezone_london = new DateTimeZone('Europe/London');
$datetimezone_client = new DateTimeZone('Australia/Canberra');
$now_client = new DateTime("now", $datetimezone_client);
$offset = $datetimezone_london->getOffset($now_client);
echo $offset;
If I flip the timezone strings, it works, but surely the above code should work too. What's happening?
getOffset() returns the offset to GMT in seconds, and London is currently on GMT, hence the return value is zero.
I believe what you need instead is:
$tz_london = new DateTimeZone('Europe/London');
$tz_client = new DateTimeZone('Australia/Canberra');
$time_london = new DateTime('now', $tz_london);
$time_client = new DateTime('now', $tz_client);
$offset = $time_client->getOffset() - $time_london->getOffset();
echo $offset;
This currently (in January) returns 39600 (11 hours). In July it returns 9 hours, and in mid October (where there's a short period when both Europe and Australia are in daylight saving) it returns 10 hours.
DateTimeZone::getOffset() works a bit differently that what most people think. It calculates the offset to GMT of the instance DateTimeZone offset for the date passed as parameter. The date passed as parameter is then converted to the same timezone as the instance (DST and other rules applying) and the offset is calculated for that date.
So your code right now calculates the offset to GMT of the timezone Europe/London.. Since Europe/London is on GMT right now (versus BMT), you are getting 0. (Try a date in August, you'll get 36000).
If you want the current difference between two timezones, use this code...
function timezone_diff($origin, $compareTo, $forDate = "now") {
$dtzOrigin = new DateTimeZone($origin);
$dtzCompareTo = new DateTimeZone($compareTo);
$compareDate = new DateTime($forDate);
$offsetOrigin = $dtzOrigin->getOffset($compareDate);
$offsetCompareTo = $dtzCompareTo->getOffset($compareDate);
return $offsetCompareTo - $offsetOrigin;
}

Categories