I have this PHP code:
$from_date = new DateTime('April-22-2016');
$from_date->format( 'Y-m-d 00:00:00' );
$from_date->setTime(0,0,0);
print ' / '. $from_date_unix = $from_date->getTimestamp();
The above code prints a Unix timestamp of 1461356160, which means
GMT: Fri, 22 Apr 2016 20:16:00 GMT
The hours are 20:16:00 - which is strange, since I already set the time to 00:00:00 via
$from_date->setTime(0,0,0);
Is my code wrong? Do I need to check something in php.ini?
The date you provided as first argument to DateTime::__construct() does not use any of the standard date and time formats understood by PHP. Therefore, it tries to identify the date and time components in the string you provided.
A print_r($from_date) immediately after it was created reveals what PHP (mis-)understood from your date:
DateTime Object
(
[date] => 2016-04-22 00:00:00.000000
[timezone_type] => 1
[timezone] => -20:16
)
Before anything else, when it starts parsing a string for date & time, PHP initialize the new DateTime object with the current date, time and timezone. Then it overwrites the components it identifies in your string as follows:
April was correctly identified as the month name;
22 is the day of the month;
for some reason I don't know now, it set the time of the new object to 00:00:00;
the rest of the string (-2016) was used as timezone offset; i.e. -20:16 hours.
Maybe the way it works sounds silly to you but since you provided it a random string, this is the best it could get out of it.
The next line of your code ($from_date->format( 'Y-m-d 00:00:00' );) produces a string and doesn't modify the DateTime object. Because you don't do anything with the string returned by DateTime::format(), the entire line is a no-op.
The next line ($from_date->setTime(0,0,0);) also doesn't have any effect on $from_date because it's time already is 00:00:00.
Now it's clear why $from_date->getTimestamp() returns the time 20:16 GMT: when it's 00:00 at the timezone with offset -20:16, on the GMT timezone there already is 20:16.
In order to get what you want you need to use the DateTime::createFromFormat() static function:
$from_date = DateTime::createFromFormat(
'!F-d-Y',
'April-22-2016',
new DateTimeZone('GMT')
);
print ' / '. $from_date_unix = $from_date->getTimestamp();
Remark the exclamation mark (!) at the start of the format specifier. It tells PHP to reset all the date and time components to the Unix Epoch. This way the generated date already has the time 00:00:00 and there is no need to set it.
Its output is:
1461283200
You can parse the DateTime object with the right format with DateTime::createFromFormat
Use it like this:
$from_date = DateTime::createFromFormat('!F-d-Y', 'April-22-2016');
$from_date->format( 'Y-m-d 00:00:00' );
print ' / '. $from_date_unix = $from_date->getTimestamp();
Related
I have some php code dynamically generating a .ics file for download. I am passing in a start date value of 08/01/2019 and when it succesfully gets imported into ical / google calendar it is off by one day, despite the epoch timestamp being correct. I am not sure what I am missing here.
I have tried reformatting the date to a different date string, than converting it to the format required for ical and that results in jan 1 1969. I am using the WordPress date_i18n() function to format the date in expected value.
$dateVal; // contains 08/01/2019
$dtstart = date_i18n("Ymd\THis\Z", strtotime( $dateVal) );
// output: 20190801T000000Z
When the event goes into the calendar, it shows my date as july 31st, 2019 at 6pm NOT the expected value of august 1st, 2019
Any ideas how I can debug this?
What I think is happening is this:
Your event is supposed to be at 8/01/2019 in your timezone, which based on the apparent offset seems to be UTC+6.
the \Z in your format string is indicating that the event is at 8/1/2019 in UTC, so when you see it on your calendar, it is adjusted to your timezone, so it gets 8 hours subtracted.
Try leaving off the \Z, I think it should just use your local timezone.
Or convert the time to UTC.
$date = new DateTime($dateVal);
$date->setTimezone(new DateTimeZone('UTC'));
$dtstart = $date->format('Ymd\THis\Z');
Assume system time is set to 2017-03-30. Then this code will convert the date wrong:
<?php
$dateTime = DateTime::createFromFormat('m-Y', '02-2017');
$converted = $dateTime->format('Y-m');
print_r($converted);
The value of $converted is
2017-03
but only when run from the browser. Run from command line, it gives the correct result 2017-02.
Anyone knows why? February does not have 30 days, so that might be a reason, but still.
Edit: Changed format from 'Y-m-d' to 'Y-m'.
Edit 2: Added information about command line vs browser.
The rules used by DateTime::__construct(), DateTime::createFromFormat() and strtotime() to parse various date & time formats and the values it uses to fill missing components are explained in the documentation.
When it parses an incomplete date, it uses the values from the current date and time for the missing components.
In your specific case, 02-2017 is converted to "February 2017" using the current day of month (30) for the missing day of month. I.e. 30 February 2017 that is then normalized to 2 March 2017.
You can tell DateTime::createFromFormat() to initialize all the components to the Unix epoch (instead of the current date & time) by placing an exclamation mark (!) in the format string:
$dateTime = DateTime::createFromFormat('!m-Y', '02-2017');
print_r($dateTime);
It outputs:
DateTime Object
(
[date] => 2017-02-01 00:00:00.000000
[timezone_type] => 3
[timezone] => UTC
)
What you have here is over-run. The process goes like this:
1) You give the dateTime object a formatted date, but without a day.
2) The dateTime object then can not use null days so instead uses todays date.
3) You state in your question that todays date is 2017-03-30 therefore to apply this to the given date value of 02-2017 would make:
30-02-2017
4) This is obviously not valid so the dateTime object over-runs this value and turns it into 02-03-2017.
You reqest an output format of Year - Month which gives you 2017-03.
Solution:
Always set a day value in your dates.
I have a PHP datetime object that I have been trying to convert into a string with DateTime::format() . But this keeps giving me a wrong date . For some reason I keep getting a date that is one day prior the day that I am running my code no matter what value I give the date.
My DateTime object -
object(DateTime) {
date => '2017-03-25 00:00:00'
timezone_type => (int) 3
timezone => 'UTC'
}
I use this to format the DateTime into a string -
$myDateObject->format('Y/m/d')
Gives me -
2017/03/23
There is absolutely no code between the line that prints the DateTime object and the line that formats the object ie there are no modifications made on the object .
If it helps the output of my server's date -u returns Fri Mar 24 06:08:39 UTC 2017 . Also if I create the date string with hours and minutes using $myDateObject->format('Y/m/d h:i') I get 2017/03/23 12:00
EDIT
The output of my date_default_timezone_get() is UTC
date('Y-m-d') gives 2017-03-24 ie today's date
Check out default time zone set in PHP
you may wanna try setting default time zone example: date_default_timezone_set('America/Toronto');
This question already has answers here:
How do you explain the result for a new \DateTime('0000-00-00 00:00:00')?
(2 answers)
Closed 7 years ago.
Beforehand, I have read this question:
How to prevent PHP to convert a DateTime object with 0000-00-00 value to -0001-11-30
But I dont get why 0000-00-00 00:00:00 changes to -0001-11-30 00:00:00 when I run this code:
$date = date_create('0000-00-00 00:00:00');
echo date_format($date, 'Y-m-d H:i:s');
When I try it with 0001-00-00 00:00:00 I get:
0000-11-30 00:00:00
and with 0001-01-01 00:00:00 I get:
0001-01-01 00:00:00
and with 0000-00-01 00:00:00:
-0001-12-01 00:00:00
Is there any specific reason why it's always a year/day/month before the nonexisting date?
Is there something wrong with the functions date_create or date_format?
I do notice that the time is displayed the right way and that's probably because the time 00:00:00 exists.
It's like #Mark Baker said, 0000-00-00 00:00:00 is an invalid date, because there is no month zero, no day zero.... so it's month 1 (Jan) - 1 (Dec of previous year) and day 1 - 1 (Goes to last day of previous month, giving 30th November).
If you see close enough about this behavior in date_create. It says DateTime will recognize any number up to 12 as a [month], and any number up to 31 as a [day]; it calculates the resulting date to be [day] days after the start of [month]. This means that when a datetime object is created with more days than are found in that month, the date will be beyond the end of the month. This also applies if the date you're create is invalid date. :)
This is a known issue with DateTime function in php. The datetime function does not have a proper error handling.
Other functions like strtotime does handle it properly.
You can refer this for more reference.
Could be your server timezone, or a time adjustment.
Try (re)setting the timezone
<?php
// get the existing timezone
echo date_default_timezone_get();
// set up the correct one for your location
date_default_timezone_set("Europe/Dublin");
// check if new timezone was applied
echo date_default_timezone_get();
?>
http://php.net/manual/en/function.date-default-timezone-set.php
I am using date function along with strtotime function to format the date.
Ex:
<?php
$input_date = '03-JUL-09 14:53';
$formatted_date = date("Y-m-d H:i:s", strtotime($input_date));
echo $formatted_date;
?>
Gives me a expected output: 2009-07-03 14:53:00
while if the input is changed to(I am removing the minute part)-
<?php
$input_date = '03-JUL-09 14';
$formatted_date = date("Y-m-d H:i:s", strtotime($input_date));
echo $formatted_date;
?>
The output here is 1970-01-01 05:30:00, which is not at all expected.
Whats the mistake I am doing and how it can be fixed.
Thanks
Amit
1970-01-01 05:30:00 is the time in India at the Unix epoch (1970-01-01 00:00:00 GMT/UTC). This means that strtotime returned either 0, or false, which was converted to 0 by date. This is because it could not process its input, as others have explained.
The function strtotime expects to be given a string containing a US English date format and will try to parse that format into a Unix timestamp.
You can use strings like
03 july 2009
now
09-07-03
09-07-03 14:00:00
+1 week 2 days 4 hours 2 seconds
last Monday
But not incomplete date format like "09-07-03 14". The parser don't understand it and returns nothing so when you call date("Y-m-d H:i:s", strtotime($input_date)); it returns the 0 timestamp (January 1 1970 00:00:00 UTC), cause it's the default value.
You have to give a right string that can be parsed.
This looks like it comes down to the inability of strtotime() to determine which numbers are what in your 2nd date string.
My best advice is to normalize your date-time value before passing it to strtotime(). Something simple like this might be enough
if ( false === strpos( $input_date, ':' ) )
{
$input_date .= ':00';
}
03-JUL-09 14 does not seem to be a valid date string, 03-JUL-09 14:00 works fine
from the php manual: strtotime — Parse about any English textual datetime description into a Unix timestamp
1970-01-01 is a typical baseline date (in ctime for example). I believe the output is formatting a value of 0 into a date, thus the 1970, and the unrelated 05:30:00 time of day.
I believe this is a fluke in attempting to format a date that does not include all the requested time elements. Can you pad the date data to generate a complete input date?
strtotime() fails to parse the second string when you remove the minute part. It doesn't know what the extra "14" means so it returns bool(false). Calling date(false) returns the same thing as date(0), i.e. it gives you the date of the UNIX epoch: January 1, 1970 00:00:00 GMT adjusted for your local timezone.