Jump to content

Is this a PHP bug, incomplete documentation, or my misunderstanding?


NotionCommotion

Recommended Posts

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?

Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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;
        }
    }

 

Link to comment
Share on other sites

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, ...)

 

  • Like 1
Link to comment
Share on other sites

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.

  1. 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
  2. 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.

Link to comment
Share on other sites

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.

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.