Recommended Server Side date validation, independent from tcl version:
if { "" != $start_date } { if {[catch { if { $start_date != [clock format [clock scan $start_date] -format %Y-%m-%d] } { ad_return_complaint 1 "<strong>[_ intranet-core.Start_Date]</strong> [lang::message::lookup "" intranet-core.IsNotaValidDate "is not a valid date"].<br> [lang::message::lookup "" intranet-core.Current_Value "Current value"]: '$start_date'<br>" } } err_msg]} { ad_return_complaint 1 "<strong>[_ intranet-core.Start_Date]</strong> [lang::message::lookup "" intranet-core.DoesNotHaveRightFormat "doesn't have the right format"].<br> [lang::message::lookup "" intranet-core.Current_Value "Current value"]: '$start_date'<br> [lang::message::lookup "" intranet-core.Expected_Format "Expected Format"]: 'YYYY-MM-DD'" } }
Evaluation of alternative solutions:
$ tclsh8.4 if { [catch { set end_date_ansi [clock format [clock scan 2011-10-33] -format %Y-%m-%d] } ""] } { ad_return_complaint 1 "Wrong date" }Problem: Will not work with dates > 31 december 2037 http://wiki.tcl.tk/1035
8.5 does not have the Y2038 problem, but does not throw an error when wrong date is passed:
$ tclsh8.5 clock format [clock scan "2040-11-31"] -format %Y-%m-%d 2040-12-01
Some experimentation however shows that the range 1 january 1902 to "31 december 2038'' is acceptable on UNIX and Windows. ...
Actually, the range depends on the OS and the version of Tcl. For instance, using Tcl 8.5 on SPARC Solaris, I see:
$ tclsh8.5 % clock format [clock scan "January 1, 2040"] Sun Jan 01 00:00:00 EST 2040
whereas on the same machine I also see:
$ tclsh8.4 % clock format [clock scan "January 1, 2040"] unable to convert date-time string "January 1, 2040" % clock format [clock scan "Dec 31, 2038"] unable to convert date-time string "Dec 31, 2038" %
Validate a date (format: dd.mm.yyyy)
proc isdate {str} { if {![regexp {^(?:(?:[0-2]\d|30)\.(?:1\d|0[^2])|31\.(?:0[13578]|1[02])|([0-1]\d|2\d)\.02)\.(\d{4})$} $str "" t y] || ($t == 29 && ($y % 4 || ($y % 100 == 0 && $y % 400)))} { return 0 } return 1 }http://snipplr.com/view/52865/comprehensive-date-validation-regex-pattern/
^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$
template::util::date::validate "2020-12-31" err_ref 0 template::util::date::validate "2020-13-31" err_ref 0
set start_date_julian [dt_ansi_to_julian_single_arg $date_ansi]
set current_date_ansi [dt_julian_to_ansi $julian_date]
clock format [clock scan "20120128"] -format {%Y-%m-%d}
set end_date_ansi [db_string get_previous_month "SELECT '$start_date_ansi'::date+'1 month'::interval-'1 day'::interval" -default 0] clock format [clock scan {+7 days} -base [clock scan {2012-04-05}] ] -format %Y-%m-%d
[clock format [clock seconds] -format {%Y-%m-%d}]
set number_days_month [db_string get_number_days_month "SELECT date_part('day','$first_day_of_month'::date + '1 month'::interval - '1 day'::interval)" -default 0]
set last_day_of_month [db_string get_number_days_month "select to_date( '$cap_year' || '-' || '$cap_month' || '-' || '$number_days_month','yyyy-mm-dd')+1 from dual;" -default 0]
set current_date_ansi [db_string julian_date_select "select to_char( to_date(:julian_date,'J'), 'YYYY-MM-DD') from dual"]
set form_start_date [lc_time_fmt [parameter::get_from_package_key -package_key "intranet-cost" -parameter DefaultStartDate -default "2010-01-01"] "%x" locale]
clock format [clock scan "$report_year-$report_month-$day_double_digit"] -format %w
SELECT user_id, day, EXTRACT('dow' from day) as u from im_hours h where EXTRACT('dow' from day) = 6 OR EXTRACT('dow' from day) = 0 order by day;
set end_date_ansi [append "" [string range $current_date_ansi 0 7] $number_days_month]
[format "%.2f" [expr {double(round(100*$val))/100}]]
[string is double -strict $var]
Using OpenACS API:
lc_parse_number - Converts a number to its canonical representation by stripping everything but the decimal seperator.
Using tcl:
lc_numeric num [ fmt ] [ locale ]Example:
lc_numeric "2003.5" "%.2f" "de_DE" 2.003,50
Calle Aprestadora 19, 12o-2a
08902 Hospitalet de Llobregat (Barcelona)
Spain
Tel Europe: +34 609 953 751
Tel US: +1 415 200 2465
Mail: info@project-open.com