Jackson
Jackson

Reputation: 5657

Date validation with the clock command

Consider the following code run on a Windows 7 system:

% info patchlevel
8.6.4
% clock scan "1995-01-35" -format "%Y-%m-%d"
791856000
% clock format [clock scan "1995-01-35" -format "%Y-%m-%d"] -format "%Y-%m-%d"
1995-02-04
%

I ran into this situation when trying to determine if a string was a valid date, I was expecting the first clock scan to fail as 35 isn't a valid day, but what happens is that I get a date 35 days after the 1st of January.

In my code I'm now comparing the output of the 2nd clock command to the original input and deciding that the string isn't really a valid date if the result is different.

Is there a better way to validate a date and is this the expected behaviour of the clock command, I can't find it described in the manual page for clock?

Upvotes: 2

Views: 1555

Answers (1)

Dinesh
Dinesh

Reputation: 16428

It is not in-built functionality in Tcl. If the dates/months are exceeding, then it is added to the successive days/months.

In your case, you are giving 35th of month January. The additional 4 days (i.e. 31 + 4 = 35) are added and calculated as month February's 4th day.

In the bizarre case that adding the given number of days yields a date that does not exist because it falls within the dropped days of the Julian-to-Gregorian conversion, the date is converted as if it was on the Julian calendar.

Adding a number of months, or a number of years, is similar; it converts the given time to a calendar date and time of day. It then adds the requisite number of months or years, and reconverts the resulting date and time of day to an absolute time.

If the resulting date is impossible because the month has too few days (for example, when adding 1 month to 31 January), the last day of the month is substituted. Thus, adding 1 month to 31 January will result in 28 February in a common year or 29 February in a leap year.

proc is_valid_date {date {date_format "%Y-%m-%d"}} {
    return [string equal [clock format [clock scan $date  -format $date_format] -format $date_format] $date]
}

The date format is an optional and defaulted to %Y-%m-%d. If the format is not matching then it will fail. You can handle the exceptions.

Output :

% is_valid_date "1995-02-28"
1
% is_valid_date "1995-01-35"
0
%

We are converting the date to a long and reverting to the date again. If both are not same, then the given input is incorrect.

Reference : clock

Upvotes: 4

Related Questions