2 registered users in last 24 hours
Working with Numbers, Date & Time
Content
Server Side Date Validation
Recommended Server Side date validation, independent from tcl version:
if { $start_date != [dt_julian_to_ansi [dt_ansi_to_julian_single_arg $start_date]] } {
ad_return_complaint 1 "<strong>Start Date</strong> doesn't have the right format.<br>
Current value: '$start_date'<br>
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"
%
Server side date validation using regular expressions
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/
Matches dd/mm/yyyy or dd/mm/yy, also correctly matches number of days in months. ie. it won't match 29th Feb 2011 but matches 29th Feb 2012
^(?:(?: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})$
Server side date validation using ad_form
Date validation is build into ad_form
Server side date validation using template::util::date
Seems broken:
template::util::date::validate "2020-12-31" err_ref
0
template::util::date::validate "2020-13-31" err_ref
0
Server side date validation using tcl - Other helpful links:
Date Type conversations & Formatting
Ansi to Julian
set start_date_julian [dt_ansi_to_julian_single_arg $date_ansi]
Julian to Ansi
set current_date_ansi [dt_julian_to_ansi $julian_date]
Formatting
clock format [clock scan "20120128"] -format {%Y-%m-%d}
Formatting in sql query
set hours_start_date [db_string get_new_start_at " select to_char(max(day), 'YYYYMMDD') from im_hours where project_id = :project_id " -default ""]
Calculation
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
Other
Date today
[clock format [clock seconds] -format {%Y-%m-%d}]
Number of days of a month
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]
Last day of a month:
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]
Get current day month:
set current_date_ansi [db_string julian_date_select "select to_char( to_date(:julian_date,'J'), 'YYYY-MM-DD') from dual"]
Localize Date (user locale):
set form_start_date [lc_time_fmt [parameter::get_from_package_key -package_key "intranet-cost" -parameter DefaultStartDate -default "2010-01-01"] "%x" locale]
DOW:
clock format [clock scan "$report_year-$report_month-$day_double_digit"] -format %w
Other:
set end_date_ansi [append "" [string range $current_date_ansi 0 7] $number_days_month]
Numbers - Formatting and rounding
Round:
[format "%.2f" [expr {double(round(100*$val))/100}]]
Check for numeric:
[string is double -strict $var]
Get Canonical representation of number
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
|