NotionCommotion Posted December 5, 2021 Share Posted December 5, 2021 I know that DateTime and its OOP and procedural cousins can accept as their first argument a date string of multiple formats, an at sign followed by an integer, "now" in either lower or uppercase, and either null or an empty string which has the same effect as "now". I was surprised, however, when I received a valid date using new Datetime('ROC'). Upon further research, found this is the time zone for Taiwan, and strings such as "utc" or "America/Shiprock" will return a valid DateTime object as well. Is this to be expected? Quote Link to comment https://forums.phpfreaks.com/topic/314276-is-this-a-php-bug-incomplete-documentation-or-my-misunderstanding/ Share on other sites More sharing options...
Barand Posted December 5, 2021 Share Posted December 5, 2021 I guess it's incomplete documentation. DateTime is full of surprises. One I found to be useful is setting a dateInterval to "next weekday" to get a list of N working days $dt = new DateTime('next monday'); $di = DateInterval::createFromDateString('next weekday'); $dp = new DatePeriod($dt, $di, 9); foreach ($dp as $d) { echo $d->format('D M jS').'<br>'; } gives Mon Dec 6th Tue Dec 7th Wed Dec 8th Thu Dec 9th Fri Dec 10th Mon Dec 13th Tue Dec 14th Wed Dec 15th Thu Dec 16th Fri Dec 17th Quote Link to comment https://forums.phpfreaks.com/topic/314276-is-this-a-php-bug-incomplete-documentation-or-my-misunderstanding/#findComment-1592455 Share on other sites More sharing options...
NotionCommotion Posted December 5, 2021 Author Share Posted December 5, 2021 Thanks Barand, I will need to take this "feature" into account. I have an array created from a CSV file and wish to identify all records where a given cell has a date in it (and not "ROC", etc). I came up with the following, but it is not impervious to "next weekday". Think I will need to also add some regex check? protected function getDateTime(string $input):?DateTimeInterface { $input = trim($input); if(!$input || strtolower($input)==='now' || $input[0] === '@') { return null; } try{ $dt = new DateTimeImmutable($input); if($input===$dt->getTimezone()->getName()) { // Don't accept timezones as a date. return null; } return $dt; } catch(\Exception $e) { return null; } } Quote Link to comment https://forums.phpfreaks.com/topic/314276-is-this-a-php-bug-incomplete-documentation-or-my-misunderstanding/#findComment-1592459 Share on other sites More sharing options...
kicken Posted December 5, 2021 Share Posted December 5, 2021 2 hours ago, NotionCommotion said: I have an array created from a CSV file and wish to identify all records where a given cell has a date in it I'd use DateTime::createFromFormat. Ideally you'd want the dates to be in a specific format. If you can't do that, I'd just try a few of the most common formats in a particular order (ie, Y-m-d, m/d/Y, ...) 1 Quote Link to comment https://forums.phpfreaks.com/topic/314276-is-this-a-php-bug-incomplete-documentation-or-my-misunderstanding/#findComment-1592461 Share on other sites More sharing options...
requinix Posted December 6, 2021 Share Posted December 6, 2021 Sorry but it is documented. Like strtotime, it will assume the input is a valid date/time string and try its best to make the most of it, and there are a bunch of different things that are supported. https://www.php.net/manual/en/datetime.formats.php Quote Link to comment https://forums.phpfreaks.com/topic/314276-is-this-a-php-bug-incomplete-documentation-or-my-misunderstanding/#findComment-1592462 Share on other sites More sharing options...
NotionCommotion Posted December 6, 2021 Author Share Posted December 6, 2021 15 hours ago, kicken said: I'd use DateTime::createFromFormat. Ideally you'd want the dates to be in a specific format. If you can't do that, I'd just try a few of the most common formats in a particular order (ie, Y-m-d, m/d/Y, ...) I don't know the format, and while I could guess using the most common and likely be correct, I would rather not need to duplicate PHP's guessing algorithms. Maybe I only confirm that it has either a hyphen or forward slash will be enough. 13 hours ago, requinix said: Sorry but it is documented. Like strtotime, it will assume the input is a valid date/time string and try its best to make the most of it, and there are a bunch of different things that are supported. https://www.php.net/manual/en/datetime.formats.php Not sorry happy it is documented, but I still don't see it. The first parameters is datetime - A date/time string. Valid formats are explained in Date and Time Formats, and can also be null, "now", and probably a few other things The second parameters is timezone - A DateTimeZone object representing the timezone of $datetime. Where does it say that if datetime is omitted, then the timezone is accepted by the first parameter. Quote Link to comment https://forums.phpfreaks.com/topic/314276-is-this-a-php-bug-incomplete-documentation-or-my-misunderstanding/#findComment-1592476 Share on other sites More sharing options...
kicken Posted December 6, 2021 Share Posted December 6, 2021 38 minutes ago, NotionCommotion said: Where does it say that if datetime is omitted, then the timezone is accepted by the first parameter. That's not what happens. A datetime string can be composed of various bits of information and one of those bits of information is a timezone. For example you could specify "2021-12-06 9:32:00 EST". In the formats documentation it says: Quote The formats are grouped by section. In most cases formats from different sections, separated by whitespace, comma or dot, can be used in the same date/time string So the example there's a "Date Format" part a "Time Format" part. In the Time Formats formats documentation, there's an entry saying it will recognize a timezone name. Quote tz "("? [A-Za-z]{1,6} ")"? | [A-Z][a-z]+([_/][A-Z][a-z]+)+ "CEST", "Europe/Amsterdam", "America/Indiana/Knox" You don't need to specify every bit of information when providing a date/time string. Missing bits will be determined based on the current time usually. As such, specifying only a timezone abbreviation/name is a valid entry and it will parse as the current time, but with the timezone set as X. 52 minutes ago, NotionCommotion said: I don't know the format, and while I could guess using the most common and likely be correct, I would rather not need to duplicate PHP's guessing algorithms And I would rather ensure I have known correct data rather than something totally unexpected like what prompted this thread. Just checking for a - or a / isn't going to help, as it'd still allow entries like "America/New_York" or "UTC-7:00" Forcing a fixed format or two in my experience works nearly all the time. You can log failures so that if a particular format occurs often you can add it to the list. I usually just inform people what the expected format is though. You make the separator flexible by using ? or * instead of a defined separator if that's one of your concerns. Eg: Y*m*d would accept both 2021-12-06 and 2021/12/06. Quote Link to comment https://forums.phpfreaks.com/topic/314276-is-this-a-php-bug-incomplete-documentation-or-my-misunderstanding/#findComment-1592477 Share on other sites More sharing options...
NotionCommotion Posted December 6, 2021 Author Share Posted December 6, 2021 1 hour ago, kicken said: That's not what happens. A datetime string can be composed of various bits of information and one of those bits of information is a timezone. For example you could specify "2021-12-06 9:32:00 EST". In the formats documentation it says: So the example there's a "Date Format" part a "Time Format" part. In the Time Formats formats documentation, there's an entry saying it will recognize a timezone name. You don't need to specify every bit of information when providing a date/time string. Missing bits will be determined based on the current time usually. As such, specifying only a timezone abbreviation/name is a valid entry and it will parse as the current time, but with the timezone set as X. Quote The $timezone parameter and the current timezone are ignored when the $datetime parameter either is a UNIX timestamp (e.g. @946684800) or specifies a timezone (e.g. 2010-01-28T15:00:00+02:00). Ah, got it! The above also says the same, and the datetime string can contain the timezone and nothing says that it needs to contain more. Not a bug, not incomplete documentation (but a little ambiguous, but my misunderstanding. Thank you for your clarification. 1 hour ago, kicken said: And I would rather ensure I have known correct data rather than something totally unexpected like what prompted this thread. Just checking for a - or a / isn't going to help, as it'd still allow entries like "America/New_York" or "UTC-7:00" Forcing a fixed format or two in my experience works nearly all the time. You can log failures so that if a particular format occurs often you can add it to the list. I usually just inform people what the expected format is though. My initial thought was to first use DateTime and then validate against false positives, but I cannot disagree with your position and will most likely do as you recommend. Quote Link to comment https://forums.phpfreaks.com/topic/314276-is-this-a-php-bug-incomplete-documentation-or-my-misunderstanding/#findComment-1592481 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.