Get date object from difference between 2 dates, timezone dependant - php

I have a date stored in a database with timezone UTC, the date is a few days/hours/minutes ahead of right now.
I then need to calculate the difference in time between right now and the given date, bearing in mind that there could be different timezones at play.
I have been doing the following but it is wrong as the timezone isn't taken into consideration.
$interval = date_create('now')->diff(date_create($listing_end_date));
//$interval->d = days
//$interval->h = hours
//$interval->i = minutes
How can I do the above with the timezone taken into account?

You need to pass a second argument to date_create telling it what time zone is represented by the date in $listing_end_date. For example, assuming the string is in UTC:
$interval = date_create('now')->diff(date_create($listing_end_date,
new DateTimeZone('UTC')));

Related

How to Substract time from datetime

I am using a timezone based script where there is deadline based on timezones. Say for example a deadline is on 7th July at 6PM for a person in IST timezone. The deadline should be 1:30 less than 6pm in Dubai as per their timezone.
I have already calculated the difference between the two timezone difference. I am stuck at deducting that calculated time from the deadline time.
I have saved the timezones in +5:40 +4:00 -4:00 this format instead of using php default ones.
Here's what I use to add and subtract time from a date.
First of all, I get the date from the database and then convert it to a DateTime object.
$date = new DateTime($date);
I use add and a DateInterval to add time. Here's an example to add hours.
$date->add(new DateInterval("PT{$hoursToAdd}H"));
And here's and example to subtract hours intead:
$date->sub(new DateInterval("PT{$hoursToSubstract}H"));
Check this out to know how to work with DateInterval and add/subtract different times: http://php.net/manual/en/class.dateinterval.php
Can you explain a little more specifically what you want to do?
You want to subtract when data already on some var inside your script or you want the SQL query needed ?
If so maybe you can use this answer ---> How to subtract 3 hours from a datetime in MySQL?
The last answer of this post maybe is the one that fit the most what you need :
Assuming you have some timezone issue and know source and destination timezone, you could convert it like so
SELECT
DATE_FORMAT(CONVERT_TZ(x.date_entered, 'UTC', 'Europe/Berlin'), '%Y-%m-%d') AS date
FROM
x
ORDER BY
date ASC;

PHP set TimeZone without changing date?

I send UNIX timestamp from javascript vat stamp = +new Date/1000 to PHP.
Then I do
//Here $d = '2015/04/03 00:00:00'
$d = new DateTime("#{$stamp}");
$d->setTimezone( new DateTimeZone( 'Pacific/Auckland' ) );
//Here $d = '2015/04/03 00:00:00' + 7:15 hrs ( 7:15 hrs is time diff between my browser & Auckland)
I want to change the timezone but keep the date to same. So, after I setTimezone to Pacific/Auckland, the date should still be '2015/04/03 00:00:00'.
Here's one way to do it.
$_date = new \DateTime($date->format('Y-m-d H:i:s'), new \DateTimeZone('<time zone>'));
I need to point out that you're asking for something nonsensical. A UNIX timestamp represents an absolute point in time. It does not represent "2015/04/03 00:00:00", because that date format can refer to a few dozen different points in time, depending on which timezone you're interpreting this string in. A UNIX timestamp doesn't have this problem, what point in time it represents is not negotiable based on timezones.
If you take an absolute point in time and want to format it as a human readable time which depends on timezones, then this human readable value will necessarily change by applying a different timezone to it. What you're asking for is to change the point in time the timestamp refers to, at which point it's just arbitrary.

Finding the difference between days

I'm having a table as follows to store future date,
email date
abc#gmail.com 8/10/2014
and I want to do is to find the difference between the above date and the sever date.
I'm using date("m/d/Y") to get the current date.
If date("m/d/Y") = 07/20/2014, then I need the answer as 21.
Please help me find the difference between those days using PHP & MySQL, or suggest a better way to find the difference in days.
You can convert date to timestamp then calculate the days:
(int)(strtotime('8/10/2014')-strtotime('07/20/2014'))/60/60/24
The easiest way would be to store your dates as timestamps, then you could subtract the current timestamp with the one you've saved in a database.
The PHP function time() returns the current timestamp – that is the number of seconds since the 1st of January 1970. You can then format a timestamp $stamp to your liking with date('m/d/Y', $stamp), for example.
Aside from facilitating arithmetic operations with dates, you can display more or less information with timestamps by formatting them with date(), as well as show different formats (July 13, 2014 vs. 07/13/2014). If you save a date as a string, e.g. "8/10/2014", it will be very complicated for you to change the format, and it won't be possible to get the correct time, for example.
Finding how long ago in days a timestamp $stamp was to the current time is very easy:
$now = time();
$days = ($stamp - $now) / (24*3600);
Use round() to get a full number if desired (e.g. 7.2309 would simply become 7).
I'd personally do it using DateTime:
Select your date out into a variable. In this instance We'll call it $DBDate
$DBDateObj = DateTime::createFromFormat('j/m/Y', $DBDate);
$TodayDateObj = new DateTime();
$interval = $TodayDateObj->diff($DBDateObj);
$daysDiff = $interval->days;
In $daysDiff you should now have the difference in days.

Date between MySQL and PHP

I have a table with a field of type date within a MySQL database. My user places a date into a field (format dd-mm-yyyy) which I convert into yyyy-mm-dd for insertion into the database. This works fine. I can see the date in there as (for example) 2012-04-04.
My issue is that I then select this record, convert the date to the format I wish to display (dd-mm-yyyy) and get 03-04-2012. I understand why, in that my database is set to UTC, however the user is on Berlin time, therefore 04-04-2012 00:00 in Berlin is 03-04-2012 23:00 UTC.
The issue means that if I then save the displayed date (03-04-2012), the next time I see it, it displays as 02-04-2012 because I saved only the date and therefore the system is assuming a 00:00 time again.
I cannot see a way around this other than setting this as a datetime type rather than a date type, however I would rather not do that as time (for various reasons) is stored in a separate field. Any suggestions?
When you inserting a record you add as datetime current UTC time, after that every user in their profile may want to/or set his timezone.
If you know the timezone of the user u can easy convert the datetime to user locale time. Because you know the differences in hours/minutes between the time.
P.S. You can store the datetime as varchar and save the unix timestamp in this field. Unix timestamp is based on current timezone I think.
UPDATE:
I think that might help
$date = time();
dump(date('d-m-Y H:i:s', $date)); // 03-04-2012 08:43:38
date_default_timezone_set('Europe/London');
dump('London: '. date('d-m-Y H:i:s', $date)); // London: 03-04-2012 11:43:38
date_default_timezone_set('Europe/Berlin');
dump('Berlin: '. date('d-m-Y H:i:s', $date)); // Berlin: 03-04-2012 12:43:38
date_default_timezone_set('Europe/Sofia');
dump('Sofia: '. date('d-m-Y H:i:s', $date)); // Sofia: 03-04-2012 13:43:38
dump function returns '<pre>'. $something .'</pre>';
UTC is the international time standard. It is similar to Greenwich Mean Time (GMT), except that UTC observes no daylight saving time (DST) and is based on a 24-hour clock. Zero (0) hours UTC is midnight GMT. The local 24-hour time convention is converted to UTC by adding or subtracting hours based on location in relation to the prime meridian, as well as local daylight saving time considerations.
First, make sure both time zones are same. Then, don't store in datatime format, use integer. Convert the date to timestamps and then store. Like
$time = time(); //get the current time stamp
//Now insert $time
Now, both places are in common ground, You may do as you like. Changing date among different timezone is rather easy.
echo gmdate("M d Y H:i:s", $time);

PHP - strtotime, specify timezone

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'))
)
);

Categories