PHP: DateTime::__construct() error - php

I keep getting the following error :
DateTime::__construct(): Failed to parse time string (46-61-9481) at position 0 (4): Unexpected character
which relates to this piece of script within an API
$dob = new DateTime(str_replace('/','-',Input::post('date_of_birth')));
$customer->date_of_birth = $dob->getTimestamp();
I have quite limited knowledge when it comes to code but, I'm wondering if anyone would be kind enough to let me know what to change to avoid these errors.

The problem here is the use of DateTime(). PHP DateTime() expects a valid date and otherwise it will throw an exception. If you still want to accept invalid date input, better to put this in a try catch block. If the date is a valid one, it will work well and otherwise it will come to catch block. In the catch block, you can set a default date such as 00/00/0000 and save to DB.
try {
$date = new DateTime('01-01-2016');
$date = $date->format('m/d/Y');
} catch (\Exception $e) {
$date = '00/00/0000';
}
echo $date;

46 is not a valid month, nor a valid day of month. A valid month or day of month never starts with a 4.
The date 46-61-9481 is invalid, hence the error.
The solution is to validate the input date prior to passing it to DateTime constructor.

Related

STRTOTIME in php returning blank value

The dataset value is returning blank, no error on logfile.
$edate = trim($_POST['txtedate']); //user inputs date 12-01-2021
$int_effective_date = new DateTime(strtotime($edate));
echo "edate:- ".$edate."<br />";
echo "strtotime_edate:- ".strtotime($edate)."<br />";
echo "dateset:- ".strtotime($int_effective_date->format('Y/m/d'));
Result:
edate:- 2021-01-12
strtotime_edate:- 1610389800
dateset:-
To paraphrase #iainn: I'm not 100% sure why you're changing back and forth between DateTime objects and function calls to strtotime?
However, I can explain the most likely issue with your code...
strtotime
Firstly, let's clarify that 12-01-2021 is in the format (d-m-Y)? Hopefully it is, in which case PHPs strtotime function understands it correctly and produces a Unix timestamp (i.e. seconds passed since start of 1970)...
strtotime("12-01-2021");
// Output: 1610409600
// Notes:
// - Possible slight variations based on locale etc.
// - Lookup: date_default_timezone_set
// - This is with "UTC"
DateTime
You then pass that timestamp to DateTime but neglect to inform DateTime what kind of timestamp it is...
$int_effective_date = new DateTime(strtotime($edate));
// Is the same as...
$int_effective_date = new DateTime(1610409600);
However, DateTime doesn't see your timestamp as incorrect and tries to process it anyway...
In the format: HisYmd
But your input is too short for that so it only matches HisY
Time => 16:10
Year => 9600
Given the lack of data DateTime then fills in the blanks with today (example: 2021-02-05)
Day => 05
Month => 02
Which give you a complete timestamp of: 9600-02-05 16:10:40
strtotime from DateTime
Your next line of code then passes that timestamp back into a strtotime call...
echo "dateset:- ".strtotime($int_effective_date->format('Y/m/d'));
// Is the same as...
echo "dateset:- ".strtotime("9600/02/05");
Now, strtotime will always return something. Which means the first problem is that you're using echo which doesn't output (bool) false.
Try:
var_dump(strtotime("9600/02/05"));
You might ask, why doesn't that happen in the linked code example from #El_Vanja?
Answer
The answer to that, I believe, is that your PHP version is not up to date and anything over the 32 bit date range is going to return (bool) false from strtotime.
To fix this specific problem I suggest you update your PHP version (and OS if you haven't moved to 64 bit!)
However, further to that, I strongly suggest you stick to the DateTime object/class. It saves you from all of these annoying bugs if nothing else...
For reference:
echo strtotime( (new DateTime("#1610409600"))->format("Y-m-d") ); // Output: 1610409600
echo strtotime( (new DateTime("2021-01-12"))->format("Y-m-d") ); // Output: 1610409600

How to parse date string to dateTime in php?

I have a date string in this format "2014-12-01 16:00:02,153". How do I parse this to a datetime format for mysql?
I am using laravel and Carbon. My code is Carbon::parse("2014-12-01 16:00:02,153");
but get an error that reads DateTime::__construct(): Failed to parse time string (2014-12-01 16:00:02,153) at position 20 (1): Unexpected character
You could use the createFromFormat method from the DateTime object :
$dateTime = DateTime::createFromFormat('Y-m-d H:i:s,u', "2014-12-01 16:00:02,153");
echo $dateTime->format('Y-m-d H:i:s');
PHP is confused by the time format you are handing over.
new DateTime("2014-12-01 16:00:02,153"); // fails
strtotime("2014-12-01 16:00:02,153"); // fails
This is because of the unexpected part with the comma at the end. Where are you getting this strange timestamp with comma seperated milliseconds from? It is unusual.
As you are asking for datetime which usually does not need any milliseconds you can do the following:
$timeparts = explode(",","2014-12-01 16:00:02,153");
Carbon::parse($timeparts[0]); // should work
$timeparts[1] is the milliseconds then.
If you want to be more precise you can round the milliseconds:
if(intval($timeparts[1]) >= 500) {
// time +1 second
}
... or you treat the milliseconds seperatly if you need em. Add them to the generated timestamp later and check the docs of Carbon.

Guessing date format with PHP

I have a user input in web-form in HTML5 type="date" field. Then this entered value (together with others) is saved as JSON document in MySQL database. Now I need to extract that date and print it into generated MS Word document with one given format. Great! But as you know HTML5 date field accepts date format depending on user locales, settings, etc. I noticed that all dates entered in different browsers are saved in DB in "Y-m-d" format. Is this really so in all the cases? Can I rely on this format for future usage? Could not find any specification information on the topic.
If one can not rely on "Y-m-d" format are there any PHP libraries for "guessing" date format?
First of all, why are you saving JSON document in MySQL database instead of some more suitable document database (e.g. MongoDB)?
Anyway, based on this and this the displayed date format differs from the actual value. The date value in the HTTP Request will be always formatted as yyyy-mm-dd, which is the ISO 8601 format and I guess it should be reliable.
In PHP you can process date strings with the DateTime class. This class supports many different date formats. For example:
// timezone is set based on your system preferences if not set
$date1 = new DateTime('2017-04-27', new DateTimeZone('+00:00'));
$date2 = new DateTime('27 April 2017', new DateTimeZone('+00:00'));
$date3 = new DateTime('2017-04-27T00:00:00+00:00');
var_dump($date1 == $date2); // bool(true)
var_dump($date1 == $date3); // bool(true)
If the date string is wrong, an exception is thrown:
try {
$date = new DateTime('2017 4 27');
} catch (Exception $e) {
echo $e->getMessage(); // DateTime::__construct(): Failed to parse time string (2017 4 27) at position 5 (4): Unexpected character
}
So, in your case you can you this class for date validation and than proper output formatting, e.g.:
$dateString = '2017-04-27T14:22:11+00:00';
try {
$date = new DateTime($dateString);
echo $date->format('Y-m-d'); // 2017-04-27
} catch (Exception $e) {
// do something else
}

Determine \DateTime has inferred a day in constructor

I am trying to make user-input accept a date to limit searching. I use the following:
try {
$begin = new \DateTime($range['begin']);
} catch (\Exception $e) {
$begin = null;
}
If the date fails to construct, then the query (not shown) is not modified.
Occasionally the users enter just a month, and it would be obvious then that the user wants to search between the first and last day of the month, and I might modify the query in a different way.
Unfortunately php infers, without other specification that the user means the first of the month. Is there any way to determine if this has happened? Another way to ask this question is how does one determine that a user has supplied a valid month without a day and distinguish that from supplying a date with first day of the month that leverages the myriad formats DateTime automatically interprets?
My first pass used date_parse, but that also infers the date.
better always to know format of input value, so then you can simple convert to datetime object, for example:
$inputFieldValue = '22/02/2017';
$date = \DateTime::createFromFormat('d/m/Y', $inputFieldValue);
if ($date instanceof \DateTime) {
echo 'input is valid date, do what you need';
} else {
echo 'input is not valid date';
}
more documentation http://php.net/manual/en/datetime.createfromformat.php

Contruct a datetime with specific format

i have a date string from my db, the date is 16/11/2010 and its format is d/m/Y, i want to modify its like this.
<?php
$date_from_db= '16/11/2010'; // format is d/m/Y
$date = new DateTime($date_from_db);
$date-> modify('+1 week');
echo $date-> format('d/m/Y') ;
?>
i have got this error
Fatal error: Uncaught exception 'Exception' with message 'DateTime::__construct(): Failed to parse time string (16/11/2012) at position 0 (1).
How can i fix this?
try
$date = DateTime::CreateFromFormat("d-m-y", "16-11-2010");
Unfortunately that is not one of the time formats supported by DateTime class constructor.
This page shows valid formats
http://www.php.net/manual/en/datetime.formats.date.php
You should use an actual SQL-compliant date field (typically YYYY-MM-DD) in your DB. Or if you can't change the way your are storing the dates, use DateTime::CreateFromFormat as suggested in other answer.
I would highly suggest using a more standard storage format though.

Categories