Zend_Date adding the timezone to a subtraction result - php

I have this code:
<?php
$start = new Zend_Date("2011-09-06T10:00:00+02:00",Zend_Date::ISO_8601);
$end = new Zend_Date("2011-09-06T10:01:00+02:00",Zend_Date::ISO_8601);
echo $end->sub($start);
?>
In short: I create two dates, with a minute's difference between them. Then I print out the difference (subtraction) between them.
The result, however, is:
01-01-1970 02:01:00
Basically, what I understand from this behaviour is that Zend_Date operates on dates without taking timezone into consideration, and then puts the timezone back in the result. Of course, this means that the subtraction result is off by the value of the timezone (+2h in my case).
What's the best way to get around this?

Yes, when echo'ing a Zend_Date, it will take your timezone into account. To get the difference formatted for GMT dates, you have to set the timezone explicitly:
$start = new Zend_Date("2011-09-06T10:00:00+02:00",Zend_Date::ISO_8601);
$end = new Zend_Date("2011-09-06T10:01:00+02:00",Zend_Date::ISO_8601);
echo $end->sub($start)->setTimezone('GMT')->get(Zend_Date::ISO_8601);
This would output: 1970-01-01T00:01:00+00:00
On a sidenote, if you do not need the dynamic localization features of Zend_Date it's best to avoid it in favor or PHP's native DateTime API. There is really no reason to use Zend_Date just because it exists in ZF. PHP's own DateTime API is faster and easier to use. Getting the time difference with the DateTime API would be
$start = new DateTime("2011-09-06T10:00:00+02:00");
$end = new DateTime("2011-09-06T10:01:00+02:00");
echo $start->diff($end)->format('%H:%I:%S');
which would output 00:01:00

Related

Converting a date from local timezone to UTC

I have a Laravel-based app that is used by people from various parts of the US.
I am capturing a timestamp in Javascript when the user takes a specific action, and then I am submitting that timestamp as form data, for the Laravel/PHP to process.
The timestamp that I am capture in Javascript is in typical "YYYY-MM-DD HH:MM:SS" format.
I have the timezone the user is in stored in a database.
I basically want to take that timestamp, and convert it to UTC time, so that all timestamps in the database are UTC.
That is where I am struggling.
I have the following PHP code:
$defaultTime = request('submitted-time-stamp'); //In this case, we'll say 2022-12-21 12:01:01
$defaultTZ = $user->time_zone; //Translates to America/Denver
$utcTime = new DateTime($defaultTime);
$convertedTime = $utcTime1->setTimeZone(new DateTimeZone('UTC'));
$formattedTime = $convertedTime->format("Y-m-d H:i:s");
echo $formattedTime;
This code – it isn't producing any errors per sé... but it is showing the wrong time. It's showing the time that it went in as, not the time converted to UTC.
Basically, if I submit "2022-12-21 12:01:01" as the time, the converted time SHOULD be "2022-12-21 19:01:01", but it's still just echoing out "2022-12-21 12:01:01".
What am I missing here?
setTimezone() changes the timezone of the object from whatever default it was created with. I.e., it means, "convert from the existing timezone to this new timezone." It does not mean, "interpret the time as if it were in this timezone." If the original string didn't contain some sort of timezone identifier, then that default is whatever your PHP config says.
$when = new DateTime('2022-12-21 12:01:01');
echo $when->getTimeZone()->getName();
This will be the same as:
echo date_default_timezone_get();
Which is probably not what you want unless all your users are in the same timezone as your server.
In order to create a DateTime object in a specific known timezone that is not the same as your server's default, you'll need one of two things -- either a timezone representation in the input string:
$when = new DateTime('2022-12-21 12:01:01 America/New_York');
Or an explicit default timezone passed as a second parameter to the DateTime constructor:
$userDefaultTzStr = 'America/New_York'; // read this value from the database
$defaultTz = new DateTimeZone($userDefaultTzStr);
$when = new DateTime('2022-12-21 12:01:01', $defaultTz);
This latter method is (probably) preferred. If the input string contains any sort of timezone identifier, that will be used and the second parameter will be ignored. But if the input string does not contain any sort of timezone identifier, then the string will be interpreted as if it were in the indicated timezone.
Using Carbon it's very trivial.
use Carbon\Carbon;
$date = Carbon::create(request('submitted-time-stamp'), $user->time_zone);
$date->tz('UTC');
echo $date->format('Y-m-d H:i:s');
It should be the same thing with Laravel's Date facade.
use Illuminate\Support\Facades\Date;
$date = Date::create(request('submitted-time-stamp'), $user->time_zone);
$date->tz('UTC');
echo $date->format('Y-m-d H:i:s');

Convert timestamp coming from SQL database to String

I am saving the timestamp in SQL as bigint(20). The number is correct and in android or https://www.epochconverter.com it works fine.
However I am not able to create a date-string based on the timestamp received from database.
First of all, the timestamp seems to come from database as a String, so I can't just say echo date("d.m.Y, $timestamp). The result is the famous 31.12.1969.
So I tried echo date("d.m.Y, strtotime($timestamp)). However, even though strtotime is said to be able to convert almost everything to a timestamp, a simple String containing a timestamp is not possible. Results still remained on the last day of Brian Adams probably favorite year.
Some progress I made by casting the $timestamp to a float value like so: echo date("d.m.Y", floatval($timestamp));. However, now things got really confusing for me. I seemed to have successfully converted my timestamp, however, date() gave me the dates around 02.09.52299.
The timestamps I am using are timestamps of current time, e.g. 1588489252657, which currently leads to the date 23.03.52307.
So all I want is to come to a date based on the timestamp 1588489252657 to see the 03.05.2020 on my screen.
Thanks for any advice!
<?php
$timestamp = 1588489252657; // Timestamp in Milliseconds
$seconds = round($timestamp/1000, 0); // Timestamp Rounded to Seconds
$date = new DateTime(); // Create PHP DateTime Object
$date->setTimestamp($seconds); // Set the Timestamp
echo $date->format('Y-m-d H:i:s'); // Specify the Required Format
The answers are pretty much in the comment sections. But I have shared this answer since this is another approach in OOP fashion. You can leverage the power of PHP's DateTime Class.
PHP Official Documentation For DateTime Class Link Below:
PHP DateTime Class
You have to transform the timestamp to seconds first.
$timestamp = 1588489252657;
$dateInUnixSeconds = round($timestamp / 1000, 0);
$date = \DateTimeImmutable::createFromFormat('U', (string) $dateInUnixSeconds);
echo $date->format('d.m.Y');
PS:
I recommend you to use the \DateTimeImmutable object to avoid mutability problems.
https://github.com/Chemaclass/php-best-practices/blob/master/technical-skills/immutability.md

Timezone formatting not returning abbreviation on certain timezones

I'm a bit confused as to why the date formatter T does not always return a timezone abbreviation.
The following code Carbon::now()->timezone('Europe/London')->format('T') returns 'BST', Carbon::now()->timezone('Europe/Stockholm')->format('T') returns 'CEST', but Carbon::now()->timezone('Asia/Bangkok')->format('T') returns '+07', which is rather confusing for the users of a scheduling system I'm building.
I would expect T to always return a 'non-numeric' indication of the timezone, is there a way to achieve this without having to resort to writing out 'Asia/Bangkok'?
It should return "ICT". It's a known bug of PHP: https://bugs.php.net/bug.php?id=74835
You get the same result without Carbon:
$date = new DateTime('now', new DateTimeZone('Asia/Bangkok'));
echo $date->format('T');

timestamp from both date & time inputs and compare php

I've been struggling to get an exact answer for this question. There are many that are close to what I'm wanting but seem to still be just off. The application of this is to ensure that a booking can't be made for a past date.
I have a form which has an input for time & another for date. Firstly, I wan't to take both of these inputs & convert them to a timestamp.
This code returns nothing
$time_date = sprintf("%s %s", $pDate, $pTime);
$objDate = DateTime::createFromFormat('H:ia d/m/Y', $time_date);
$stamp = $objDate->getTimestamp();
echo $stamp;
So I've have tried using something like this
$pDate = $_POST['pDate'];
$pTime = $_POST['pTime'];
$full_date = $pDate . ' ' . $pTime;
$timestamp = strtotime($full_date);
echo $timestamp;
But for some reason it is returning an incorrect timestamp. (i've been using an online converter) 02/06/2014 as date & 12:23am as time, is not 1401625380. This according to the converter is Sun, 01 Jun 2014 12:23:00 GMT.
Does someone have working code for returning a timestamp of both time & date inputs?
Secondly I want to compare this timestamp with a specified one & check to see if it is greater than. I've created a timestamp for my timezone with this
$date = new DateTime(null, new DateTimeZone('Pacific/Auckland'));
$cDate = $date->getTimestamp();
echo $cDate;
and will simply have an if statement which compares the two and echos the appropriate message.
I feel as though there are multiple question on here that are ALMOST what I'm wanting to achieve but I can't manage to get them working. Apologies for the near duplicate.
Note: I'm using ajax to post form data (if this could possibly interfere).
Your second code snipped is correct. Assuming it's in datetime format (Y-m-d H:i:s).
From php manual about strtotime():
Each parameter of this function uses the default time zone unless a time zone is specified in that parameter.
Check your PHP default time zone with date_default_timezone_get() function.
To compare two dates, be sure they both are in same time zones.
For datetime inputs I personally use jQuery UI timepicker addon.
you receiving the time and date in string format - so i don't believe the ajax can interfere.
as for your question:
first of all - find out what is the locale timezone of your server. you can do it by this function: date_default_timezone_get.
if the answer doesn't suit you - you can use its "sister": date_default_timezone_set, and change it to whatever value you need (like 'Pacific/Auckland' - see the documentation there). it is also recommended to return it to the original value after you finish your stuff.
i believe fixing your locale timezone will solve your issue.

Time format conversion

I need to convert a specific date format into local time (Europe/Sarajevo), I have the time in this format 2013-02-17T15:00:00Z which I don't really understand and this is why I don't know how to convert it to the Europe/Sarajevo time, who knows maybe it is already Sarajevo time, I don't know...
OK I can parse it and remove the T and Z and get a time but these letters mean something, probably they affect the result time...
The result time is for example 2013-02-17 18:00:00, probably there will be a difference due to the letters T and Z which are probably time offset.
Use DateTime. It's much better for working with timezones:
$datetime = new DateTime('2013-02-17T15:00:00Z');
$datetime->setTimeZone(new DateTimeZone('Europe/Sarajevo'));
echo $datetime->format('c');
Reference
DateTime
DateTimeZone
See it in action
You can use php date function like this
$date = '2013-02-17T15:00:00Z';
echo date('Y-m-d H:i:s',strtotime($date));
See the Manual

Categories