PHP convert week number and year back to Carbon? - php

I'm using format W-Y for weeknumber & year.
e.g. the final week of 2018 would be represented as '52-2018'.
But I can't get Carbon or DateTime to convert it back.
>>> Carbon::createFromFormat('W-Y', '01-2018')
InvalidArgumentException with message 'The format separator does not match
The separation symbol could not be found
Trailing data'

DateTime::createFromFormat (which is what Carbon extends) doesn't support the W formatting character, unfortunately.
The easiest way to work around this is to create a new DateTime (or Carbon) instance, and use the native setISODate method to set the year and week number:
$str = '01-2018';
list ($week, $year) = explode('-', $str);
$d = new DateTime;
$d->setISODate($year, $week);
See https://3v4l.org/g33QV

A string of the form '01-2018' can also be converted to '2018W01' with preg_replace, which can then be processed directly by DateTime and Carbon.
$str = '01-2018';
$dateTime = new DateTime(preg_replace('~^(\d\d)-(\d\d\d\d)$~','$2W$1',$str));
While with the accepted solution we always get the current time for the date, here it is always 00:00:00.
Demo: https://3v4l.org/mo6dQ

Related

DateTime::createFromFormat How to set custom init date

At 2022-09-30 i encountered weird behaviour of DateTime::createFromFormat, for pattern 'Y-m' and date '2022-02' it returns 2022-03-02, now i know this is happening cause php will populate missing date values.
But today i wanna write some test cases with pattern !Y-m or Y-m| but i cant reproduce the error because now is 2022-10-03 so $d->createFromFormat('Y-m', '2022-02'); will not overflow to march, so can i somehow force \DateTime::createFromFormat to return value as if it was launched on 2022-09-30 ?
I also tried creating new instance of DateTime and call createFromFormat on it, instead of static call:
$d1 = new \DateTime('2022-09-30');
$d2 = $d1->createFromFormat('Y-m', '2022-02');
print_r($d2->format('Y-m-d')); // returns 2022-02-03, expected 2022-03-02
Also i am using php 7.4
Parsing an incomplete date and defining the missing components user-specifically is possible with the class Dt.
$dateFragment = '2022-02';
$dateInit = '2000-01-15 04:30';
$regEx = '/^(?<Y>\d{4})-(?<m>\d{1,2})$/'; //4 digit year, hyphen, 1-2 digit month
$timeZone = "Europe/Berlin";
$date = Dt::createFromRegExFormat($regEx,$dateFragment,$timeZone,$dateInit);
echo $date->format('Y-m-d H:i'); //2022-02-15 04:30
The dateFragment returns only the month and year. A regular expression defines how the fragment is to be interpreted. Regular expressions are far more powerful than normal formatting. The missing information (day, hour, minute) is taken from dateInit.
The definition of createFromFormat (https://www.php.net/manual/en/datetime.createfromformat.php) says that the arguments are in reverse order.

Parse date with 7 digits in microseconds part

I'm trying to parse Atom feed and it contains date like this one
2019-02-28T06:11:12.0775241Z
The problem with it is microseconds 0775241, which is 7 digits, but php can handle only 6 digits. This date is probably generated with Go lang.
If it had 6 digits, Y-m-d\TH:i:s.u\Z would work fine.
UPD: it is for DateTime::createFromFormat, can't use new DateTime etc.
Looking for solution, may be you had same problem as me.
That is a standard easily recognisable date format. Use the DateTime class
$d = new DateTime("2019-02-28T06:11:12.0775241Z");
echo $d->format('d/m/y H:i:s');
RESULT
28/02/19 06:11:12
Of course you can output in any format you like
I know this is not the best solution but you can handle it with Carbon
$datetime = Carbon::parse('2019-03-13T18:07:54.5810814+03:30');
dump($datetime);
// Carbon #1552487874 {#358
// date: 2019-03-13 18:07:54.581081 +03:30
// }

PHP convert string into date time

I have a php string from db it is 20/11/2017 I want to convert it milliseconds.
It's my code to doing that.
$the_date = "20/11/2017";
$mill_sec_date = strtotime($the_date);
var_dump($mill_sec_date);
But it does not print any thing rather than
bool(false);
What is the problem and how can i solve it ????
When using slashes to separate parts of the date, PHP recognizes the format as MM/DD/YYYY. Which makes your date invalid because there is no 20th month. If you want to use the format where day and month is swapped, you need to use hyphens, like DD-MM-YYYY.
$time = strtotime('10/16/2003');
$newformat = date('Y-m-d',$time);
print_r($newformat);
Use DateTime class to call function createFromFormat
$date = date_create_from_format('d/M/Y:H:i:s', $string);
$date->getTimestamp();
Most likely you got the date format wrong, see
here for a list of supported date and time formats:
This section describes all the different formats that the strtotime(), DateTime and date_create() parser understands.
You string is not accept by the strtotime, you can use createFromFormat set set the with the format type of the time string like below, you can also check the live demo. And you also can refer to this answer
var_dump(DateTime::createFromFormat('d/m/Y', "20/11/2017"));

PHP week date conversion

My date formatted like this "2000-5-1". First digit represents 4 digit year. The second is number of week in year, and the last one represents number of day in week.
No matter what I do, function always returns false, my code is following:
date_create_from_format("Y-W-N", "2000-5-1")
(docs)
Please avoid solutions that are using magic words like "+1 day" etc.
Creating a DateTime object from a compound format with year/week/day is described in the compound formats section of the supported date and time formats section of the PHP Docs:
$x = new DateTime("2000-W05-1");
var_dump($x);
Note that the week number requires a leading zero
Result is a DateTime object for 2000-01-31
If you look at the documantation of DateTime::createFromFormat (which is what you are using with an alias) and date(), there is not a 100% overlap of the formats, so you have a problem.
This is what I found that you could use as an alternative: DateTime::setISODate
$date = explode('-','2000-5-1');
$newDate = new DateTime();
$newDate->setISODate($date[0], $date[1], $date[2]);
setISODate will take the year, week and day as explained in the documentation to create a DateTime object.

Convert and insert two date formats MYSQL

I'm facing an issue with managinging dates, some dates pass others dont. I want to produce an insertable date for mysql. there are two possible types of post dates
yyyy-mm-dd //should go without conversion
m/d/yyyy // should be converted
I'm using this
$date = $_REQUEST['date'];
$date_regex = '/(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d/';
if(preg_match($date_regex, $date)){
$date = DateTime::createFromFormat('m/d/Y',$date)->format('Y-m-d');}
problems
I realised this regex is failing for dates like
2/5/2013
but has been working for
12/12/2013
so I removed it BUT still
DateTime::createFromFormat('m/d/Y',$date)->format('Y-m-d');
is also failing for m/d/yyyy
This date thing has got my head spinning for the last 6 hours.
In this case, there is no need to use DateTime::createFromFormat because m/d/yyyy is one of the recognized date formats (see "American month, day and year"). Just convert it to a DateTime object and let the constructor handle the format and forget the regex:
$date = $_REQUEST['date'];
$datetime = new DateTime($date);
$datex = $datetime->format('Y-m-d');
The reason DateTime::createFromFormat('m/d/Y',$date) fails for dates like 2/5/2013 is because you are forcing it to be specifically 'm/d/Y' and that date does not fit that pattern. You can see a list of all date formats here. Specifically, m expects there to be a leading zero (like 02), so when you give it one without that, it won't recognize it. Same goes for d. In this case you would have to use n and j respectively. But, like I said, let the constructor do the hard work for you.

Categories