clock scan -format works, kindof - but it allows 0-99 months and 0-99
days ;(
A regexp can get more specific, but you still have corner cases like
30 days in Feb.
And I'm sure there's a better method than writing a parser with a
DaysPerMonth table and leap year checker and all the rest.
The closest I've got is a [clock scan $date -format "Y%/%m/%d"], then
clock format that back to the same format and compare. But a valid
date input like 2007/9/14 doesn't work because the output of clock
format has leading zeros on the day and month.
Twylite
Another approach is to never let the date be
invalid by using a specialised datefield entry
widget.
There's one I wrote in tklib with documentation
at http://tcllib.sourceforge.net/doc/datefield.html.
An updated version which allows more flexible date format
can be found at http://wiki.tcl.tk/Tcl-onlyDatefield.
There's also one in iwidgets.
Keith
Am I missing something?
Alan
Unfortunately this irritates our users who don't want to have to point
and click a date they can just type in.
> There's one I wrote in tklib with documentation
> athttp://tcllib.sourceforge.net/doc/datefield.html.
> An updated version which allows more flexible date format
> can be found athttp://wiki.tcl.tk/Tcl-onlyDatefield.
Thanks for the info on the updated version. We do want a date picker
(that can be used as an option), but US format mm/dd/yyyy doesn't cut
it in this country ;/
Cheers,
Twylite
Hmm ... [clock scan 2007/99/99] -> 6198760800 (Tcl 8.5b7). Perhaps
this is a bug, not sure. It seems that Tcl's clock command (in 8.5 at
least) is happy to say "2007/01/01 + n months + m days" and figure out
the resulting seconds since epoch.
The reason we can't use [clock scan] without -format is that the
behaviour gets mighty confusing when people enter 01/04/2007. On my
PC that is interpreted as m/d/Y despite my regional/locale settings
being d/m/Y. This is especially confusing if you are in a country
where d/m/Y is the norm. i.e. we have to use -format to ensure
accurate interpretation of what the user enters.
Regards,
Twylite
> An updated version which allows more flexible date format
> can be found athttp://wiki.tcl.tk/Tcl-onlyDatefield.
Will the updated version also be appearing in tklib?
Although you have to load an external package I find the mentry
package satisfies my needs
http://www.nemethi.de/mentry/mentry.html
(My Documents) 60 % package present ActiveTcl
8.4.14.0.272572
(My Documents) 57 % clock scan 2007/99/99
unable to convert date-time string "2007/99/99"
> The reason we can't use [clock scan] without -format is that the
> behaviour gets mighty confusing when people enter 01/04/2007. On my
> PC that is interpreted as m/d/Y despite my regional/locale settings
> being d/m/Y. This is especially confusing if you are in a country
> where d/m/Y is the norm. i.e. we have to use -format to ensure
> accurate interpretation of what the user enters.
I only mentioned the lack of -format in case it was something
format-specific. I looks more likely to be something in 8.5. As you see,
and as I should have mentioned before, I'm using 8.4.
Thanks for your clarification. As a matter of interest, how will you
determine whether your users are entering d/m/Y or m/d/Y? :-)
Alan
> clock scan -format works, kindof - but it allows 0-99 months and 0-99
> days ;(
How about using "clock scan -format" and then back "clock format -format"
with the same format. If the result is the same as the original string, the
entry was valid.
-mi
Here is how I do it, some parts might be helpful:
proc ::qw::filter::combine_date_parts {
array
date_attr
format
} {
upvar $array ARRAY
if {[info exists ARRAY($date_attr)]} {
set scan_date $ARRAY($date_attr)
} else {
array set DATE_PARTS [array get ARRAY ${date_attr}.*]
set current_time [ns_time];# seconds
foreach {PART FMT} [list year %Y month %m day %d hour %H minute %M
second %S timezone %Z] {
set ELEMENT ARRAY(${date_attr}.${PART})
if {![info exists $ELEMENT] || [string equal "" [set $ELEMENT]]}
{
set $PART [ns_fmttime $current_time $FMT]
} else {
set $PART [set $ELEMENT]
}
puts "DATE PART: '$PART' = '[set $PART]'"
}
set scan_date "${year}-${month}-${day} ${hour}:${minute}:${second}
$timezone"
}
# catch an invalid date and convert to gmt
if {[catch {
set ARRAY($date_attr) [clock format [clock scan $scan_date] -format
$format -gmt 1]
} err ]} {
puts "Date '$scan_date' is invalid for attribute $date_attr"
return -code error
}
array unset ARRAY ${date_attr}.*
}
In the above the input format is usually: "%Y-%m-%d %H:%M:%S GMT".