summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--library/clock.tcl1147
1 files changed, 696 insertions, 451 deletions
diff --git a/library/clock.tcl b/library/clock.tcl
index 32911b3..d85c731 100644
--- a/library/clock.tcl
+++ b/library/clock.tcl
@@ -14,6 +14,8 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#----------------------------------------------------------------------
+# Modified and optimized 2012 by Serg G. Brester (sebres)
+#----------------------------------------------------------------------
# We must have message catalogs that support the root locale, and
# we need access to the Registry on Windows systems.
@@ -301,7 +303,7 @@ proc ::tcl::clock::Initialize {} {
# been made to make a reasonable guess, but this table needs to be
# taken with a grain of salt.
- variable WinZoneInfo [dict create {*}{
+ variable WinZoneInfo [::tcl::dict::create {*}{
{-43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Kwajalein
{-39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Midway
{-36000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Honolulu
@@ -390,50 +392,50 @@ proc ::tcl::clock::Initialize {} {
{ julianDay } 1 {}
{ era century yearOfCentury month dayOfMonth } 2 {
- dict set date year [expr { 100 * [dict get $date century]
- + [dict get $date yearOfCentury] }]
+ ::tcl::dict::set date year [expr { 100 * [::tcl::dict::get $date century]
+ + [::tcl::dict::get $date yearOfCentury] }]
set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
$changeover]
}
{ era century yearOfCentury dayOfYear } 2 {
- dict set date year [expr { 100 * [dict get $date century]
- + [dict get $date yearOfCentury] }]
+ ::tcl::dict::set date year [expr { 100 * [::tcl::dict::get $date century]
+ + [::tcl::dict::get $date yearOfCentury] }]
set date [GetJulianDayFromEraYearDay $date[set date {}] \
$changeover]
}
{ century yearOfCentury month dayOfMonth } 3 {
- dict set date era CE
- dict set date year [expr { 100 * [dict get $date century]
- + [dict get $date yearOfCentury] }]
+ ::tcl::dict::set date era CE
+ ::tcl::dict::set date year [expr { 100 * [::tcl::dict::get $date century]
+ + [::tcl::dict::get $date yearOfCentury] }]
set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
$changeover]
}
{ century yearOfCentury dayOfYear } 3 {
- dict set date era CE
- dict set date year [expr { 100 * [dict get $date century]
- + [dict get $date yearOfCentury] }]
+ ::tcl::dict::set date era CE
+ ::tcl::dict::set date year [expr { 100 * [::tcl::dict::get $date century]
+ + [::tcl::dict::get $date yearOfCentury] }]
set date [GetJulianDayFromEraYearDay $date[set date {}] \
$changeover]
}
{ iso8601Century iso8601YearOfCentury iso8601Week dayOfWeek } 3 {
- dict set date era CE
- dict set date iso8601Year \
- [expr { 100 * [dict get $date iso8601Century]
- + [dict get $date iso8601YearOfCentury] }]
+ ::tcl::dict::set date era CE
+ ::tcl::dict::set date iso8601Year \
+ [expr { 100 * [::tcl::dict::get $date iso8601Century]
+ + [::tcl::dict::get $date iso8601YearOfCentury] }]
set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \
$changeover]
}
{ yearOfCentury month dayOfMonth } 4 {
set date [InterpretTwoDigitYear $date[set date {}] $baseTime]
- dict set date era CE
+ ::tcl::dict::set date era CE
set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
$changeover]
}
{ yearOfCentury dayOfYear } 4 {
set date [InterpretTwoDigitYear $date[set date {}] $baseTime]
- dict set date era CE
+ ::tcl::dict::set date era CE
set date [GetJulianDayFromEraYearDay $date[set date {}] \
$changeover]
}
@@ -441,7 +443,7 @@ proc ::tcl::clock::Initialize {} {
set date [InterpretTwoDigitYear \
$date[set date {}] $baseTime \
iso8601YearOfCentury iso8601Year]
- dict set date era CE
+ ::tcl::dict::set date era CE
set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \
$changeover]
}
@@ -493,40 +495,40 @@ proc ::tcl::clock::Initialize {} {
seconds 1 {}
{ hourAMPM minute second amPmIndicator } 2 {
- dict set date secondOfDay [InterpretHMSP $date]
+ ::tcl::dict::set date secondOfDay [InterpretHMSP $date]
}
{ hour minute second } 2 {
- dict set date secondOfDay [InterpretHMS $date]
+ ::tcl::dict::set date secondOfDay [InterpretHMS $date]
}
{ hourAMPM minute amPmIndicator } 3 {
- dict set date second 0
- dict set date secondOfDay [InterpretHMSP $date]
+ ::tcl::dict::set date second 0
+ ::tcl::dict::set date secondOfDay [InterpretHMSP $date]
}
{ hour minute } 3 {
- dict set date second 0
- dict set date secondOfDay [InterpretHMS $date]
+ ::tcl::dict::set date second 0
+ ::tcl::dict::set date secondOfDay [InterpretHMS $date]
}
{ hourAMPM amPmIndicator } 4 {
- dict set date minute 0
- dict set date second 0
- dict set date secondOfDay [InterpretHMSP $date]
+ ::tcl::dict::set date minute 0
+ ::tcl::dict::set date second 0
+ ::tcl::dict::set date secondOfDay [InterpretHMSP $date]
}
{ hour } 4 {
- dict set date minute 0
- dict set date second 0
- dict set date secondOfDay [InterpretHMS $date]
+ ::tcl::dict::set date minute 0
+ ::tcl::dict::set date second 0
+ ::tcl::dict::set date secondOfDay [InterpretHMS $date]
}
{ } 5 {
- dict set date secondOfDay 0
+ ::tcl::dict::set date secondOfDay 0
}
}
# Legacy time zones, used primarily for parsing RFC822 dates.
- variable LegacyTimeZone [dict create \
+ variable LegacyTimeZone [::tcl::dict::create \
gmt +0000 \
ut +0000 \
utc +0000 \
@@ -667,7 +669,6 @@ proc ::tcl::clock::format { args } {
lassign [ParseFormatArgs {*}$args] format locale timezone
set locale [string tolower $locale]
- set clockval [lindex $args 0]
# Get the data for time changes in the given zone
@@ -676,7 +677,7 @@ proc ::tcl::clock::format { args } {
}
if {![info exists TZData($timezone)]} {
if {[catch {SetupTimeZone $timezone} retval opts]} {
- dict unset opts -errorinfo
+ ::tcl::dict::unset opts -errorinfo
return -options $opts $retval
}
}
@@ -685,17 +686,14 @@ proc ::tcl::clock::format { args } {
# name in the 'FormatProc' array to avoid losing its internal
# representation, which contains the name resolution.
- set procName formatproc'$format'$locale
- set procName [namespace current]::[string map {: {\:} \\ {\\}} $procName]
- if {[info exists FormatProc($procName)]} {
- set procName $FormatProc($procName)
- } else {
+ #set procName formatproc'
+ set procName '$format'$locale
+ if {![info exists FormatProc($procName)]} {
set FormatProc($procName) \
- [ParseClockFormatFormat $procName $format $locale]
+ [ParseClockFormatFormat formatproc[string map {: {\:} \\ {\\}} $procName] $format $locale]
}
- return [$procName $clockval $timezone]
-
+ $FormatProc($procName) [lindex $args 0] $timezone
}
#----------------------------------------------------------------------
@@ -721,7 +719,9 @@ proc ::tcl::clock::ParseClockFormatFormat {procName format locale} {
# Map away the locale-dependent composite format groups
- EnterLocale $locale oldLocale
+ if { $locale ne {c} && $locale ne [mclocale] } {
+ EnterLocale $locale oldLocale
+ }
# Change locale if a fresh locale has been given on the command line.
@@ -740,7 +740,7 @@ proc ::tcl::clock::ParseClockFormatFormat {procName format locale} {
# Return either the error or the proc name
if { $status == 1 } {
- if { [lindex [dict get $opts -errorcode] 0] eq {clock} } {
+ if { [lindex [::tcl::dict::get $opts -errorcode] 0] eq {CLOCK} } {
return -code error $result
} else {
return -options $opts $result
@@ -792,7 +792,7 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
[list @DAYS_OF_WEEK_ABBREV@ \
[list [mc DAYS_OF_WEEK_ABBREV]]] \
{ [lindex @DAYS_OF_WEEK_ABBREV@ \
- [expr {[dict get $date dayOfWeek] \
+ [expr {[::tcl::dict::get $date dayOfWeek] \
% 7}]]}]
}
A { # Day of week, spelt out.
@@ -802,7 +802,7 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
[list @DAYS_OF_WEEK_FULL@ \
[list [mc DAYS_OF_WEEK_FULL]]] \
{ [lindex @DAYS_OF_WEEK_FULL@ \
- [expr {[dict get $date dayOfWeek] \
+ [expr {[::tcl::dict::get $date dayOfWeek] \
% 7}]]}]
}
b - h { # Name of month, abbreviated.
@@ -812,7 +812,7 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
[list @MONTHS_ABBREV@ \
[list [mc MONTHS_ABBREV]]] \
{ [lindex @MONTHS_ABBREV@ \
- [expr {[dict get $date month]-1}]]}]
+ [expr {[::tcl::dict::get $date month]-1}]]}]
}
B { # Name of month, spelt out
append formatString %s
@@ -821,20 +821,20 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
[list @MONTHS_FULL@ \
[list [mc MONTHS_FULL]]] \
{ [lindex @MONTHS_FULL@ \
- [expr {[dict get $date month]-1}]]}]
+ [expr {[::tcl::dict::get $date month]-1}]]}]
}
C { # Century number
append formatString %02d
append substituents \
- { [expr {[dict get $date year] / 100}]}
+ { [expr {[::tcl::dict::get $date year] / 100}]}
}
d { # Day of month, with leading zero
append formatString %02d
- append substituents { [dict get $date dayOfMonth]}
+ append substituents { [::tcl::dict::get $date dayOfMonth]}
}
e { # Day of month, without leading zero
append formatString %2d
- append substituents { [dict get $date dayOfMonth]}
+ append substituents { [::tcl::dict::get $date dayOfMonth]}
}
E { # Format group in a locale-dependent
# alternative era
@@ -861,23 +861,23 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
# week number
append formatString %02d
append substituents \
- { [expr { [dict get $date iso8601Year] % 100 }]}
+ { [expr { [::tcl::dict::get $date iso8601Year] % 100 }]}
}
G { # Four-digit year relative to ISO8601
# week number
append formatString %02d
- append substituents { [dict get $date iso8601Year]}
+ append substituents { [::tcl::dict::get $date iso8601Year]}
}
H { # Hour in the 24-hour day, leading zero
append formatString %02d
append substituents \
- { [expr { [dict get $date localSeconds] \
+ { [expr { [::tcl::dict::get $date localSeconds] \
/ 3600 % 24}]}
}
I { # Hour AM/PM, with leading zero
append formatString %02d
append substituents \
- { [expr { ( ( ( [dict get $date localSeconds] \
+ { [expr { ( ( ( [::tcl::dict::get $date localSeconds] \
% 86400 ) \
+ 86400 \
- 3600 ) \
@@ -886,23 +886,23 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
}
j { # Day of year (001-366)
append formatString %03d
- append substituents { [dict get $date dayOfYear]}
+ append substituents { [::tcl::dict::get $date dayOfYear]}
}
J { # Julian Day Number
append formatString %07ld
- append substituents { [dict get $date julianDay]}
+ append substituents { [::tcl::dict::get $date julianDay]}
}
k { # Hour (0-23), no leading zero
append formatString %2d
append substituents \
- { [expr { [dict get $date localSeconds]
+ { [expr { [::tcl::dict::get $date localSeconds]
/ 3600
% 24 }]}
}
l { # Hour (12-11), no leading zero
append formatString %2d
append substituents \
- { [expr { ( ( ( [dict get $date localSeconds]
+ { [expr { ( ( ( [::tcl::dict::get $date localSeconds]
% 86400 )
+ 86400
- 3600 )
@@ -911,12 +911,12 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
}
m { # Month number, leading zero
append formatString %02d
- append substituents { [dict get $date month]}
+ append substituents { [::tcl::dict::get $date month]}
}
M { # Minute of the hour, leading zero
append formatString %02d
append substituents \
- { [expr { [dict get $date localSeconds]
+ { [expr { [::tcl::dict::get $date localSeconds]
/ 60
% 60 }]}
}
@@ -925,7 +925,7 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
}
N { # Month number, no leading zero
append formatString %2d
- append substituents { [dict get $date month]}
+ append substituents { [::tcl::dict::get $date month]}
}
O { # A format group in the locale's
# alternative numerals
@@ -944,7 +944,7 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
[list set AM [string toupper [mc AM]]] \n \
[list set PM [string toupper [mc PM]]] \n
append substituents \
- { [expr {(([dict get $date localSeconds]
+ { [expr {(([::tcl::dict::get $date localSeconds]
% 86400) < 43200) ?
$AM : $PM}]}
}
@@ -954,7 +954,7 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
[list set am [mc AM]] \n \
[list set pm [mc PM]] \n
append substituents \
- { [expr {(([dict get $date localSeconds]
+ { [expr {(([::tcl::dict::get $date localSeconds]
% 86400) < 43200) ?
$am : $pm}]}
@@ -965,13 +965,13 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
}
s { # Seconds from the Posix Epoch
append formatString %s
- append substituents { [dict get $date seconds]}
+ append substituents { [::tcl::dict::get $date seconds]}
}
S { # Second of the minute, with
# leading zero
append formatString %02d
append substituents \
- { [expr { [dict get $date localSeconds]
+ { [expr { [::tcl::dict::get $date localSeconds]
% 60 }]}
}
t { # A literal tab character
@@ -979,20 +979,20 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
}
u { # Day of the week (1-Monday, 7-Sunday)
append formatString %1d
- append substituents { [dict get $date dayOfWeek]}
+ append substituents { [::tcl::dict::get $date dayOfWeek]}
}
U { # Week of the year (00-53). The
# first Sunday of the year is the
# first day of week 01
append formatString %02d
append preFormatCode {
- set dow [dict get $date dayOfWeek]
+ set dow [::tcl::dict::get $date dayOfWeek]
if { $dow == 7 } {
set dow 0
}
incr dow
set UweekNumber \
- [expr { ( [dict get $date dayOfYear]
+ [expr { ( [::tcl::dict::get $date dayOfYear]
- $dow + 7 )
/ 7 }]
}
@@ -1000,21 +1000,21 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
}
V { # The ISO8601 week number
append formatString %02d
- append substituents { [dict get $date iso8601Week]}
+ append substituents { [::tcl::dict::get $date iso8601Week]}
}
w { # Day of the week (0-Sunday,
# 6-Saturday)
append formatString %1d
append substituents \
- { [expr { [dict get $date dayOfWeek] % 7 }]}
+ { [expr { [::tcl::dict::get $date dayOfWeek] % 7 }]}
}
W { # Week of the year (00-53). The first
# Monday of the year is the first day
# of week 01.
append preFormatCode {
set WweekNumber \
- [expr { ( [dict get $date dayOfYear]
- - [dict get $date dayOfWeek]
+ [expr { ( [::tcl::dict::get $date dayOfYear]
+ - [::tcl::dict::get $date dayOfWeek]
+ 7 )
/ 7 }]
}
@@ -1024,21 +1024,21 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
y { # The two-digit year of the century
append formatString %02d
append substituents \
- { [expr { [dict get $date year] % 100 }]}
+ { [expr { [::tcl::dict::get $date year] % 100 }]}
}
Y { # The four-digit year
append formatString %04d
- append substituents { [dict get $date year]}
+ append substituents { [::tcl::dict::get $date year]}
}
z { # The time zone as hours and minutes
# east (+) or west (-) of Greenwich
append formatString %s
append substituents { [FormatNumericTimeZone \
- [dict get $date tzOffset]]}
+ [::tcl::dict::get $date tzOffset]]}
}
Z { # The name of the time zone
append formatString %s
- append substituents { [dict get $date tzName]}
+ append substituents { [::tcl::dict::get $date tzName]}
}
% { # A literal percent character
append formatString %%
@@ -1057,16 +1057,16 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
[string map \
[list @BCE@ [list [mc BCE]] \
@CE@ [list [mc CE]]] \
- {[dict get {BCE @BCE@ CE @CE@} \
- [dict get $date era]]}]
+ {[::tcl::dict::get {BCE @BCE@ CE @CE@} \
+ [::tcl::dict::get $date era]]}]
}
C { # Locale-dependent era
append formatString %s
- append substituents { [dict get $date localeEra]}
+ append substituents { [::tcl::dict::get $date localeEra]}
}
y { # Locale-dependent year of the era
append preFormatCode {
- set y [dict get $date localeYear]
+ set y [::tcl::dict::get $date localeYear]
if { $y >= 0 && $y < 100 } {
set Eyear [lindex $localeNumerals $y]
} else {
@@ -1089,14 +1089,14 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
append formatString %s
append substituents \
{ [lindex $localeNumerals \
- [dict get $date dayOfMonth]]}
+ [::tcl::dict::get $date dayOfMonth]]}
}
H - k { # Hour of the day in alternative
# numerals
append formatString %s
append substituents \
{ [lindex $localeNumerals \
- [expr { [dict get $date localSeconds]
+ [expr { [::tcl::dict::get $date localSeconds]
/ 3600
% 24 }]]}
}
@@ -1105,7 +1105,7 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
append formatString %s
append substituents \
{ [lindex $localeNumerals \
- [expr { ( ( ( [dict get $date localSeconds]
+ [expr { ( ( ( [::tcl::dict::get $date localSeconds]
% 86400 )
+ 86400
- 3600 )
@@ -1115,14 +1115,14 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
m { # Month number in alternative numerals
append formatString %s
append substituents \
- { [lindex $localeNumerals [dict get $date month]]}
+ { [lindex $localeNumerals [::tcl::dict::get $date month]]}
}
M { # Minute of the hour in alternative
# numerals
append formatString %s
append substituents \
{ [lindex $localeNumerals \
- [expr { [dict get $date localSeconds]
+ [expr { [::tcl::dict::get $date localSeconds]
/ 60
% 60 }]]}
}
@@ -1131,7 +1131,7 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
append formatString %s
append substituents \
{ [lindex $localeNumerals \
- [expr { [dict get $date localSeconds]
+ [expr { [::tcl::dict::get $date localSeconds]
% 60 }]]}
}
u { # Day of the week (Monday=1,Sunday=7)
@@ -1139,21 +1139,21 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
append formatString %s
append substituents \
{ [lindex $localeNumerals \
- [dict get $date dayOfWeek]]}
+ [::tcl::dict::get $date dayOfWeek]]}
}
w { # Day of the week (Sunday=0,Saturday=6)
# in alternative numerals
append formatString %s
append substituents \
{ [lindex $localeNumerals \
- [expr { [dict get $date dayOfWeek] % 7 }]]}
+ [expr { [::tcl::dict::get $date dayOfWeek] % 7 }]]}
}
y { # Year of the century in alternative
# numerals
append formatString %s
append substituents \
{ [lindex $localeNumerals \
- [expr { [dict get $date year] % 100 }]]}
+ [expr { [::tcl::dict::get $date year] % 100 }]]}
}
default { # Unknown format group
append formatString %%O $char
@@ -1213,7 +1213,7 @@ proc ::tcl::clock::scan { args } {
\"$cmdName string\
?-base seconds?\
?-format string? ?-gmt boolean?\
- ?-locale LOCALE? ?-timezone ZONE?\""
+ ?-locale LOCALE? ?-timezone ZONE? ?-valid 1|0?\""
}
# Set defaults
@@ -1224,6 +1224,7 @@ proc ::tcl::clock::scan { args } {
set gmt 0
set locale c
set timezone [GetSystemTimeZone]
+ set validate 1
# Pick up command line options.
@@ -1245,11 +1246,14 @@ proc ::tcl::clock::scan { args } {
-t - -ti - -tim - -time - -timez - -timezo - -timezon - -timezone {
set timezone $value
}
+ -v - -valid {
+ set validate $value
+ }
default {
return -code error \
-errorcode [list CLOCK badSwitch $flag] \
"bad switch \"$flag\",\
- must be -base, -format, -gmt, -locale or -timezone"
+ must be -base, -format, -gmt, -locale, -timezone or -valid"
}
}
}
@@ -1283,38 +1287,18 @@ proc ::tcl::clock::scan { args } {
"legacy \[clock scan\] does not support -locale"
}
- return [FreeScan $string $base $timezone $locale]
- }
-
- # Change locale if a fresh locale has been given on the command line.
-
- EnterLocale $locale oldLocale
-
- set status [catch {
-
- # Map away the locale-dependent composite format groups
-
- set scanner [ParseClockScanFormat $format $locale]
- $scanner $string $base $timezone
-
- } result opts]
-
- # Restore the locale
-
- if { [info exists oldLocale] } {
- mclocale $oldLocale
+ return [FreeScan $string $base $timezone $locale $validate]
}
- if { $status == 1 } {
- if { [lindex [dict get $opts -errorcode] 0] eq {clock} } {
- return -code error $result
- } else {
- return -options $opts $result
- }
- } else {
- return $result
+ # Map away the locale-dependent composite format groups
+
+ set procName '$format'$locale
+ variable ScanProc
+ if {![info exists ScanProc($procName)]} {
+ set ScanProc($procName) \
+ [ParseClockScanFormat $format $locale scanproc[string map {: {\:} \\ {\\}} $procName]]
}
-
+ $ScanProc($procName) $string $base $timezone $validate
}
#----------------------------------------------------------------------
@@ -1335,14 +1319,14 @@ proc ::tcl::clock::scan { args } {
#
#----------------------------------------------------------------------
-proc ::tcl::clock::FreeScan { string base timezone locale } {
+proc ::tcl::clock::FreeScan { string base timezone locale {validate 1} } {
variable TZData
# Get the data for time changes in the given zone
if {[catch {SetupTimeZone $timezone} retval opts]} {
- dict unset opts -errorinfo
+ ::tcl::dict::unset opts -errorinfo
return -options $opts $retval
}
@@ -1353,7 +1337,7 @@ proc ::tcl::clock::FreeScan { string base timezone locale } {
$base \
$TZData($timezone) \
2361222]
- dict set date secondOfDay [expr { [dict get $date localSeconds]
+ ::tcl::dict::set date secondOfDay [expr { [::tcl::dict::get $date localSeconds]
% 86400 }]
# Parse the date. The parser will return a list comprising
@@ -1362,9 +1346,9 @@ proc ::tcl::clock::FreeScan { string base timezone locale } {
set status [catch {
Oldscan $string \
- [dict get $date year] \
- [dict get $date month] \
- [dict get $date dayOfMonth]
+ [::tcl::dict::get $date year] \
+ [::tcl::dict::get $date month] \
+ [::tcl::dict::get $date dayOfMonth]
} result]
if { $status != 0 } {
return -code error "unable to convert date-time string \"$string\": $result"
@@ -1386,10 +1370,10 @@ proc ::tcl::clock::FreeScan { string base timezone locale } {
incr y 2000
}
}
- dict set date era CE
- dict set date year $y
- dict set date month $m
- dict set date dayOfMonth $d
+ ::tcl::dict::set date era CE
+ ::tcl::dict::set date year $y
+ ::tcl::dict::set date month $m
+ ::tcl::dict::set date dayOfMonth $d
if { $parseTime eq {} } {
set parseTime 0
}
@@ -1407,28 +1391,38 @@ proc ::tcl::clock::FreeScan { string base timezone locale } {
[expr { 60 * $minEast + 3600 * $dstFlag }]]
SetupTimeZone $timezone
}
- dict set date tzName $timezone
+ ::tcl::dict::set date tzName $timezone
# Assemble date, time, zone into seconds-from-epoch
set date [GetJulianDayFromEraYearMonthDay $date[set date {}] 2361222]
if { $parseTime ne {} } {
- dict set date secondOfDay $parseTime
+ ::tcl::dict::set date secondOfDay $parseTime
} elseif { [llength $parseWeekday] != 0
|| [llength $parseOrdinalMonth] != 0
|| ( [llength $parseRel] != 0
&& ( [lindex $parseRel 0] != 0
|| [lindex $parseRel 1] != 0 ) ) } {
- dict set date secondOfDay 0
+ ::tcl::dict::set date secondOfDay 0
}
- dict set date localSeconds \
+ if {$validate} {
+ if {[catch {
+ ValidDate $date $string
+ } result opts]} {
+ if { [lindex [::tcl::dict::get $opts -errorcode] 0] eq {CLOCK} } {
+ ::tcl::dict::unset opts -errorinfo
+ }
+ return -options $opts -code error -level 2 $result
+ }
+ }
+ ::tcl::dict::set date localSeconds \
[expr { -210866803200
- + ( 86400 * wide([dict get $date julianDay]) )
- + [dict get $date secondOfDay] }]
- dict set date tzName $timezone
+ + ( 86400 * wide([::tcl::dict::get $date julianDay]) )
+ + [::tcl::dict::get $date secondOfDay] }]
+ ::tcl::dict::set date tzName $timezone
set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) 2361222]
- set seconds [dict get $date seconds]
+ set seconds [::tcl::dict::get $date seconds]
# Do relative times
@@ -1445,25 +1439,25 @@ proc ::tcl::clock::FreeScan { string base timezone locale } {
lassign $parseWeekday dayOrdinal dayOfWeek
set date2 [GetDateFields $seconds $TZData($timezone) 2361222]
- dict set date2 era CE
+ ::tcl::dict::set date2 era CE
set jdwkday [WeekdayOnOrBefore $dayOfWeek \
- [expr { [dict get $date2 julianDay]
+ [expr { [::tcl::dict::get $date2 julianDay]
+ 6 }]]
incr jdwkday [expr { 7 * $dayOrdinal }]
if { $dayOrdinal > 0 } {
incr jdwkday -7
}
- dict set date2 secondOfDay \
- [expr { [dict get $date2 localSeconds] % 86400 }]
- dict set date2 julianDay $jdwkday
- dict set date2 localSeconds \
+ ::tcl::dict::set date2 secondOfDay \
+ [expr { [::tcl::dict::get $date2 localSeconds] % 86400 }]
+ ::tcl::dict::set date2 julianDay $jdwkday
+ ::tcl::dict::set date2 localSeconds \
[expr { -210866803200
- + ( 86400 * wide([dict get $date2 julianDay]) )
- + [dict get $date secondOfDay] }]
- dict set date2 tzName $timezone
+ + ( 86400 * wide([::tcl::dict::get $date2 julianDay]) )
+ + [::tcl::dict::get $date secondOfDay] }]
+ ::tcl::dict::set date2 tzName $timezone
set date2 [ConvertLocalToUTC $date2[set date2 {}] $TZData($timezone) \
2361222]
- set seconds [dict get $date2 seconds]
+ set seconds [::tcl::dict::get $date2 seconds]
}
@@ -1473,13 +1467,13 @@ proc ::tcl::clock::FreeScan { string base timezone locale } {
lassign $parseOrdinalMonth monthOrdinal monthNumber
if { $monthOrdinal > 0 } {
- set monthDiff [expr { $monthNumber - [dict get $date month] }]
+ set monthDiff [expr { $monthNumber - [::tcl::dict::get $date month] }]
if { $monthDiff <= 0 } {
incr monthDiff 12
}
incr monthOrdinal -1
} else {
- set monthDiff [expr { [dict get $date month] - $monthNumber }]
+ set monthDiff [expr { [::tcl::dict::get $date month] - $monthNumber }]
if { $monthDiff >= 0 } {
incr monthDiff -12
}
@@ -1525,17 +1519,50 @@ proc ::tcl::clock::FreeScan { string base timezone locale } {
#
#----------------------------------------------------------------------
-proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
+proc ::tcl::clock::ParseClockScanFormat {formatString locale procName} {
# Check whether the format has been parsed previously, and return
# the existing recognizer if it has.
-
- set procName scanproc'$formatString'$locale
- set procName [namespace current]::[string map {: {\:} \\ {\\}} $procName]
- if { [namespace which $procName] != {} } {
+ if {[namespace which $procName] ne {}} {
return $procName
}
+ # Map away the locale-dependent composite format groups
+
+ if { $locale ne {c} && $locale ne [mclocale] } {
+ EnterLocale $locale oldLocale
+ }
+
+ # Change locale if a fresh locale has been given on the command line.
+
+ set status [catch {
+
+ ParseClockScanFormat2 $formatString $locale $procName
+
+ } result opts]
+
+ # Restore the locale
+
+ if { [info exists oldLocale] } {
+ mclocale $oldLocale
+ }
+
+ # Return either the error or the proc name
+
+ if { $status == 1 } {
+ if { [lindex [::tcl::dict::get $opts -errorcode] 0] eq {CLOCK} } {
+ return -code error $result
+ } else {
+ return -options $opts $result
+ }
+ } else {
+ return $result
+ }
+
+}
+
+proc ::tcl::clock::ParseClockScanFormat2 {formatString locale procName} {
+
variable DateParseActions
variable TimeParseActions
@@ -1558,7 +1585,7 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
set re {^[[:space:]]*}
set captureCount 0
set postcode {}
- set fieldSet [dict create]
+ set fieldSet [::tcl::dict::create]
set fieldCount 0
set postSep {}
set state {}
@@ -1592,15 +1619,15 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
i {7 1 2 3 4 5 6} \
abr [mc DAYS_OF_WEEK_ABBREV] \
full [mc DAYS_OF_WEEK_FULL] {
- dict set l [string tolower $abr] $i
- dict set l [string tolower $full] $i
+ ::tcl::dict::set l [string tolower $abr] $i
+ ::tcl::dict::set l [string tolower $full] $i
incr i
}
lassign [UniquePrefixRegexp $l] regex lookup
append re ( $regex )
- dict set fieldSet dayOfWeek [incr fieldCount]
- append postcode "dict set date dayOfWeek \[" \
- "dict get " [list $lookup] " " \
+ ::tcl::dict::set fieldSet dayOfWeek [incr fieldCount]
+ append postcode "::tcl::dict::set date dayOfWeek \[" \
+ "::tcl::dict::get " [list $lookup] " " \
\[ {string tolower $field} [incr captureCount] \] \
"\]\n"
}
@@ -1611,29 +1638,29 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
abr [mc MONTHS_ABBREV] \
full [mc MONTHS_FULL] {
incr i
- dict set l [string tolower $abr] $i
- dict set l [string tolower $full] $i
+ ::tcl::dict::set l [string tolower $abr] $i
+ ::tcl::dict::set l [string tolower $full] $i
}
lassign [UniquePrefixRegexp $l] regex lookup
append re ( $regex )
- dict set fieldSet month [incr fieldCount]
- append postcode "dict set date month \[" \
- "dict get " [list $lookup] \
+ ::tcl::dict::set fieldSet month [incr fieldCount]
+ append postcode "::tcl::dict::set date month \[" \
+ "::tcl::dict::get " [list $lookup] \
" " \[ {string tolower $field} \
[incr captureCount] \] \
"\]\n"
}
C { # Gregorian century
append re \\s*(\\d\\d?)
- dict set fieldSet century [incr fieldCount]
- append postcode "dict set date century \[" \
+ ::tcl::dict::set fieldSet century [incr fieldCount]
+ append postcode "::tcl::dict::set date century \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
d - e { # Day of month
append re \\s*(\\d\\d?)
- dict set fieldSet dayOfMonth [incr fieldCount]
- append postcode "dict set date dayOfMonth \[" \
+ ::tcl::dict::set fieldSet dayOfMonth [incr fieldCount]
+ append postcode "::tcl::dict::set date dayOfMonth \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
@@ -1642,65 +1669,65 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
}
g { # ISO8601 2-digit year
append re \\s*(\\d\\d)
- dict set fieldSet iso8601YearOfCentury \
+ ::tcl::dict::set fieldSet iso8601YearOfCentury \
[incr fieldCount]
append postcode \
- "dict set date iso8601YearOfCentury \[" \
+ "::tcl::dict::set date iso8601YearOfCentury \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
G { # ISO8601 4-digit year
append re \\s*(\\d\\d)(\\d\\d)
- dict set fieldSet iso8601Century [incr fieldCount]
- dict set fieldSet iso8601YearOfCentury \
+ ::tcl::dict::set fieldSet iso8601Century [incr fieldCount]
+ ::tcl::dict::set fieldSet iso8601YearOfCentury \
[incr fieldCount]
append postcode \
- "dict set date iso8601Century \[" \
+ "::tcl::dict::set date iso8601Century \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n" \
- "dict set date iso8601YearOfCentury \[" \
+ "::tcl::dict::set date iso8601YearOfCentury \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
H - k { # Hour of day
append re \\s*(\\d\\d?)
- dict set fieldSet hour [incr fieldCount]
- append postcode "dict set date hour \[" \
+ ::tcl::dict::set fieldSet hour [incr fieldCount]
+ append postcode "::tcl::dict::set date hour \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
I - l { # Hour, AM/PM
append re \\s*(\\d\\d?)
- dict set fieldSet hourAMPM [incr fieldCount]
- append postcode "dict set date hourAMPM \[" \
+ ::tcl::dict::set fieldSet hourAMPM [incr fieldCount]
+ append postcode "::tcl::dict::set date hourAMPM \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
j { # Day of year
append re \\s*(\\d\\d?\\d?)
- dict set fieldSet dayOfYear [incr fieldCount]
- append postcode "dict set date dayOfYear \[" \
+ ::tcl::dict::set fieldSet dayOfYear [incr fieldCount]
+ append postcode "::tcl::dict::set date dayOfYear \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
J { # Julian Day Number
append re \\s*(\\d+)
- dict set fieldSet julianDay [incr fieldCount]
- append postcode "dict set date julianDay \[" \
+ ::tcl::dict::set fieldSet julianDay [incr fieldCount]
+ append postcode "::tcl::dict::set date julianDay \[" \
"::scan \$field" [incr captureCount] " %ld" \
"\]\n"
}
m - N { # Month number
append re \\s*(\\d\\d?)
- dict set fieldSet month [incr fieldCount]
- append postcode "dict set date month \[" \
+ ::tcl::dict::set fieldSet month [incr fieldCount]
+ append postcode "::tcl::dict::set date month \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
M { # Minute
append re \\s*(\\d\\d?)
- dict set fieldSet minute [incr fieldCount]
- append postcode "dict set date minute \[" \
+ ::tcl::dict::set fieldSet minute [incr fieldCount]
+ append postcode "::tcl::dict::set date minute \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
@@ -1715,9 +1742,9 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
[string tolower [mc PM]] 1]
lassign [UniquePrefixRegexp $l] regex lookup
append re ( $regex )
- dict set fieldSet amPmIndicator [incr fieldCount]
- append postcode "dict set date amPmIndicator \[" \
- "dict get " [list $lookup] " \[string tolower " \
+ ::tcl::dict::set fieldSet amPmIndicator [incr fieldCount]
+ append postcode "::tcl::dict::set date amPmIndicator \[" \
+ "::tcl::dict::get " [list $lookup] " \[string tolower " \
"\$field" \
[incr captureCount] \
"\]\]\n"
@@ -1725,8 +1752,8 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
Q { # Hi, Jeff!
append re {Stardate\s+([-+]?\d+)(\d\d\d)[.](\d)}
incr captureCount
- dict set fieldSet seconds [incr fieldCount]
- append postcode {dict set date seconds } \[ \
+ ::tcl::dict::set fieldSet seconds [incr fieldCount]
+ append postcode {::tcl::dict::set date seconds } \[ \
{ParseStarDate $field} [incr captureCount] \
{ $field} [incr captureCount] \
{ $field} [incr captureCount] \
@@ -1738,14 +1765,14 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
# whether the field is actually within
# the range of a wide integer.
append re {\s*([-+]?\d+)}
- dict set fieldSet seconds [incr fieldCount]
- append postcode {dict set date seconds } \[ \
+ ::tcl::dict::set fieldSet seconds [incr fieldCount]
+ append postcode {::tcl::dict::set date seconds } \[ \
{ScanWide $field} [incr captureCount] \] \n
}
S { # Second
append re \\s*(\\d\\d?)
- dict set fieldSet second [incr fieldCount]
- append postcode "dict set date second \[" \
+ ::tcl::dict::set fieldSet second [incr fieldCount]
+ append postcode "::tcl::dict::set date second \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
@@ -1755,7 +1782,7 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
u - w { # Day number within week, 0 or 7 == Sun
# 1=Mon, 6=Sat
append re \\s*(\\d)
- dict set fieldSet dayOfWeek [incr fieldCount]
+ ::tcl::dict::set fieldSet dayOfWeek [incr fieldCount]
append postcode {::scan $field} [incr captureCount] \
{ %d dow} \n \
{
@@ -1766,7 +1793,7 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
-errorcode [list CLOCK badDayOfWeek] \
"day of week is greater than 7"
}
- dict set date dayOfWeek $dow
+ ::tcl::dict::set date dayOfWeek $dow
}
}
U { # Week of year. The
@@ -1778,8 +1805,8 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
V { # Week of ISO8601 year
append re \\s*(\\d\\d?)
- dict set fieldSet iso8601Week [incr fieldCount]
- append postcode "dict set date iso8601Week \[" \
+ ::tcl::dict::set fieldSet iso8601Week [incr fieldCount]
+ append postcode "::tcl::dict::set date iso8601Week \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
@@ -1791,33 +1818,33 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
}
y { # Two-digit Gregorian year
append re \\s*(\\d\\d?)
- dict set fieldSet yearOfCentury [incr fieldCount]
- append postcode "dict set date yearOfCentury \[" \
+ ::tcl::dict::set fieldSet yearOfCentury [incr fieldCount]
+ append postcode "::tcl::dict::set date yearOfCentury \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
Y { # 4-digit Gregorian year
append re \\s*(\\d\\d)(\\d\\d)
- dict set fieldSet century [incr fieldCount]
- dict set fieldSet yearOfCentury [incr fieldCount]
+ ::tcl::dict::set fieldSet century [incr fieldCount]
+ ::tcl::dict::set fieldSet yearOfCentury [incr fieldCount]
append postcode \
- "dict set date century \[" \
+ "::tcl::dict::set date century \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n" \
- "dict set date yearOfCentury \[" \
+ "::tcl::dict::set date yearOfCentury \[" \
"::scan \$field" [incr captureCount] " %d" \
"\]\n"
}
z - Z { # Time zone name
append re {(?:([-+]\d\d(?::?\d\d(?::?\d\d)?)?)|([[:alnum:]]{1,4}))}
- dict set fieldSet tzName [incr fieldCount]
+ ::tcl::dict::set fieldSet tzName [incr fieldCount]
append postcode \
{if } \{ { $field} [incr captureCount] \
{ ne "" } \} { } \{ \n \
- {dict set date tzName $field} \
+ {::tcl::dict::set date tzName $field} \
$captureCount \n \
\} { else } \{ \n \
- {dict set date tzName } \[ \
+ {::tcl::dict::set date tzName } \[ \
{ConvertLegacyTimeZone $field} \
[incr captureCount] \] \n \
\} \n \
@@ -1840,24 +1867,24 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
set d {}
foreach triple [mc LOCALE_ERAS] {
lassign $triple t symbol year
- dict set d [string tolower $symbol] $year
+ ::tcl::dict::set d [string tolower $symbol] $year
}
lassign [UniquePrefixRegexp $d] regex lookup
append re (?: $regex )
}
E {
set l {}
- dict set l [string tolower [mc BCE]] BCE
- dict set l [string tolower [mc CE]] CE
- dict set l b.c.e. BCE
- dict set l c.e. CE
- dict set l b.c. BCE
- dict set l a.d. CE
+ ::tcl::dict::set l [string tolower [mc BCE]] BCE
+ ::tcl::dict::set l [string tolower [mc CE]] CE
+ ::tcl::dict::set l b.c.e. BCE
+ ::tcl::dict::set l c.e. CE
+ ::tcl::dict::set l b.c. BCE
+ ::tcl::dict::set l a.d. CE
lassign [UniquePrefixRegexp $l] regex lookup
append re ( $regex )
- dict set fieldSet era [incr fieldCount]
- append postcode "dict set date era \["\
- "dict get " [list $lookup] \
+ ::tcl::dict::set fieldSet era [incr fieldCount]
+ append postcode "::tcl::dict::set date era \["\
+ "::tcl::dict::get " [list $lookup] \
{ } \[ {string tolower $field} \
[incr captureCount] \] \
"\]\n"
@@ -1882,62 +1909,62 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
d - e {
lassign [LocaleNumeralMatcher $locale] regex lookup
append re $regex
- dict set fieldSet dayOfMonth [incr fieldCount]
- append postcode "dict set date dayOfMonth \[" \
- "dict get " [list $lookup] " \$field" \
+ ::tcl::dict::set fieldSet dayOfMonth [incr fieldCount]
+ append postcode "::tcl::dict::set date dayOfMonth \[" \
+ "::tcl::dict::get " [list $lookup] " \$field" \
[incr captureCount] \
"\]\n"
}
H - k {
lassign [LocaleNumeralMatcher $locale] regex lookup
append re $regex
- dict set fieldSet hour [incr fieldCount]
- append postcode "dict set date hour \[" \
- "dict get " [list $lookup] " \$field" \
+ ::tcl::dict::set fieldSet hour [incr fieldCount]
+ append postcode "::tcl::dict::set date hour \[" \
+ "::tcl::dict::get " [list $lookup] " \$field" \
[incr captureCount] \
"\]\n"
}
I - l {
lassign [LocaleNumeralMatcher $locale] regex lookup
append re $regex
- dict set fieldSet hourAMPM [incr fieldCount]
- append postcode "dict set date hourAMPM \[" \
- "dict get " [list $lookup] " \$field" \
+ ::tcl::dict::set fieldSet hourAMPM [incr fieldCount]
+ append postcode "::tcl::dict::set date hourAMPM \[" \
+ "::tcl::dict::get " [list $lookup] " \$field" \
[incr captureCount] \
"\]\n"
}
m {
lassign [LocaleNumeralMatcher $locale] regex lookup
append re $regex
- dict set fieldSet month [incr fieldCount]
- append postcode "dict set date month \[" \
- "dict get " [list $lookup] " \$field" \
+ ::tcl::dict::set fieldSet month [incr fieldCount]
+ append postcode "::tcl::dict::set date month \[" \
+ "::tcl::dict::get " [list $lookup] " \$field" \
[incr captureCount] \
"\]\n"
}
M {
lassign [LocaleNumeralMatcher $locale] regex lookup
append re $regex
- dict set fieldSet minute [incr fieldCount]
- append postcode "dict set date minute \[" \
- "dict get " [list $lookup] " \$field" \
+ ::tcl::dict::set fieldSet minute [incr fieldCount]
+ append postcode "::tcl::dict::set date minute \[" \
+ "::tcl::dict::get " [list $lookup] " \$field" \
[incr captureCount] \
"\]\n"
}
S {
lassign [LocaleNumeralMatcher $locale] regex lookup
append re $regex
- dict set fieldSet second [incr fieldCount]
- append postcode "dict set date second \[" \
- "dict get " [list $lookup] " \$field" \
+ ::tcl::dict::set fieldSet second [incr fieldCount]
+ append postcode "::tcl::dict::set date second \[" \
+ "::tcl::dict::get " [list $lookup] " \$field" \
[incr captureCount] \
"\]\n"
}
u - w {
lassign [LocaleNumeralMatcher $locale] regex lookup
append re $regex
- dict set fieldSet dayOfWeek [incr fieldCount]
- append postcode "set dow \[dict get " [list $lookup] \
+ ::tcl::dict::set fieldSet dayOfWeek [incr fieldCount]
+ append postcode "set dow \[::tcl::dict::get " [list $lookup] \
{ $field} [incr captureCount] \] \n \
{
if { $dow == 0 } {
@@ -1947,15 +1974,15 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
-errorcode [list CLOCK badDayOfWeek] \
"day of week is greater than 7"
}
- dict set date dayOfWeek $dow
+ ::tcl::dict::set date dayOfWeek $dow
}
}
y {
lassign [LocaleNumeralMatcher $locale] regex lookup
append re $regex
- dict set fieldSet yearOfCentury [incr fieldCount]
- append postcode {dict set date yearOfCentury } \[ \
- {dict get } [list $lookup] { $field} \
+ ::tcl::dict::set fieldSet yearOfCentury [incr fieldCount]
+ append postcode {::tcl::dict::set date yearOfCentury } \[ \
+ {::tcl::dict::get } [list $lookup] { $field} \
[incr captureCount] \] \n
}
default {
@@ -1989,18 +2016,18 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
{input string does not match supplied format}
}
append procBody \}\n
- append procBody "set date \[dict create\]" \n
- append procBody {dict set date tzName $timeZone} \n
+ append procBody "set date \[::tcl::dict::create\]" \n
+ append procBody {::tcl::dict::set date tzName $timeZone} \n
append procBody $postcode
append procBody [list set changeover [mc GREGORIAN_CHANGE_DATE]] \n
# Get time zone if needed
- if { ![dict exists $fieldSet seconds]
- && ![dict exists $fieldSet starDate] } {
- if { [dict exists $fieldSet tzName] } {
+ if { ![::tcl::dict::exists $fieldSet seconds]
+ && ![::tcl::dict::exists $fieldSet starDate] } {
+ if { [::tcl::dict::exists $fieldSet tzName] } {
append procBody {
- set timeZone [dict get $date tzName]
+ set timeZone [::tcl::dict::get $date tzName]
}
}
append procBody {
@@ -2018,30 +2045,34 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
# Assemble seconds, and convert local nominal time to UTC.
- if { ![dict exists $fieldSet seconds]
- && ![dict exists $fieldSet starDate] } {
+ if { ![::tcl::dict::exists $fieldSet seconds]
+ && ![::tcl::dict::exists $fieldSet starDate] } {
append procBody {
- if { [dict get $date julianDay] > 5373484 } {
+ if { [::tcl::dict::get $date julianDay] > 5373484 } {
return -code error -errorcode [list CLOCK dateTooLarge] \
"requested date too large to represent"
}
- dict set date localSeconds \
+ ::tcl::dict::set date localSeconds \
[expr { -210866803200
- + ( 86400 * wide([dict get $date julianDay]) )
- + [dict get $date secondOfDay] }]
+ + ( 86400 * wide([::tcl::dict::get $date julianDay]) )
+ + [::tcl::dict::get $date secondOfDay] }]
}
append procBody {
set date [::tcl::clock::ConvertLocalToUTC $date[set date {}] \
$TZData($timeZone) \
$changeover]
+
+ if {$validate} {
+ ValidDate $date $string
+ }
}
}
# Return result
- append procBody {return [dict get $date seconds]} \n
+ append procBody {return [::tcl::dict::get $date seconds]} \n
- proc $procName { string baseTime timeZone } $procBody
+ proc $procName { string baseTime timeZone {validate 1} } $procBody
# puts [list proc $procName [list string baseTime timeZone] $procBody]
@@ -2071,21 +2102,21 @@ proc ::tcl::clock::LocaleNumeralMatcher {l} {
variable LocaleNumeralCache
- if { ![dict exists $LocaleNumeralCache $l] } {
+ if { ![::tcl::dict::exists $LocaleNumeralCache $l] } {
set d {}
set i 0
set sep \(
foreach n [mc LOCALE_NUMERALS] {
- dict set d $n $i
+ ::tcl::dict::set d $n $i
regsub -all {[^[:alnum:]]} $n \\\\& subex
append re $sep $subex
set sep |
incr i
}
append re \)
- dict set LocaleNumeralCache $l [list $re $d]
+ ::tcl::dict::set LocaleNumeralCache $l [list $re $d]
}
- return [dict get $LocaleNumeralCache $l]
+ return [::tcl::dict::get $LocaleNumeralCache $l]
}
@@ -2121,8 +2152,8 @@ proc ::tcl::clock::UniquePrefixRegexp { data } {
# prefix. The 'prefixMapping' dictionary will have keys that
# are prefixes of keys and values that correspond to the keys.
- set prefixMapping [dict create]
- set successors [dict create {} {}]
+ set prefixMapping [::tcl::dict::create]
+ set successors [::tcl::dict::create {} {}]
# Walk the key-value pairs
@@ -2133,15 +2164,15 @@ proc ::tcl::clock::UniquePrefixRegexp { data } {
set prefix {}
foreach char [split $key {}] {
set oldPrefix $prefix
- dict set successors $oldPrefix $char {}
+ ::tcl::dict::set successors $oldPrefix $char {}
append prefix $char
# Put the prefixes in the 'prefixMapping' and 'successors'
# dictionaries
- dict lappend prefixMapping $prefix $value
- if { ![dict exists $successors $prefix] } {
- dict set successors $prefix {}
+ ::tcl::dict::lappend prefixMapping $prefix $value
+ if { ![::tcl::dict::exists $successors $prefix] } {
+ ::tcl::dict::set successors $prefix {}
}
}
}
@@ -2150,13 +2181,13 @@ proc ::tcl::clock::UniquePrefixRegexp { data } {
# those that are the full keys
set uniquePrefixMapping {}
- dict for { key valueList } $prefixMapping {
+ ::tcl::dict::for { key valueList } $prefixMapping {
if { [llength $valueList] == 1 } {
- dict set uniquePrefixMapping $key [lindex $valueList 0]
+ ::tcl::dict::set uniquePrefixMapping $key [lindex $valueList 0]
}
}
foreach { key value } $data {
- dict set uniquePrefixMapping $key $value
+ ::tcl::dict::set uniquePrefixMapping $key $value
}
# Construct the re.
@@ -2197,7 +2228,7 @@ proc ::tcl::clock::MakeUniquePrefixRegexp { successors
# Get the characters that may follow the current prefix string
- set schars [lsort -ascii [dict keys [dict get $successors $prefixString]]]
+ set schars [lsort -ascii [::tcl::dict::keys [::tcl::dict::get $successors $prefixString]]]
if { [llength $schars] == 0 } {
return {}
}
@@ -2207,7 +2238,7 @@ proc ::tcl::clock::MakeUniquePrefixRegexp { successors
# parentheses.
set re {}
- if { [dict exists $uniquePrefixMapping $prefixString]
+ if { [::tcl::dict::exists $uniquePrefixMapping $prefixString]
|| [llength $schars] > 1 } {
append re "(?:"
}
@@ -2228,7 +2259,7 @@ proc ::tcl::clock::MakeUniquePrefixRegexp { successors
# optional. Otherwise, if there is more than one successor character,
# close the non-capturing parentheses.
- if { [dict exists $uniquePrefixMapping $prefixString] } {
+ if { [::tcl::dict::exists $uniquePrefixMapping $prefixString] } {
append re ")?"
} elseif { [llength $schars] > 1 } {
append re ")"
@@ -2284,11 +2315,11 @@ proc ::tcl::clock::MakeParseCodeFromFields { dateFields parseActions } {
set fieldPos [list]
set ok true
foreach field $fieldSet {
- if { ! [dict exists $dateFields $field] } {
+ if { ! [::tcl::dict::exists $dateFields $field] } {
set ok 0
break
}
- lappend fieldPos [dict get $dateFields $field]
+ lappend fieldPos [::tcl::dict::get $dateFields $field]
}
# Quit if we don't have a complete set of fields
@@ -2351,7 +2382,9 @@ proc ::tcl::clock::MakeParseCodeFromFields { dateFields parseActions } {
#----------------------------------------------------------------------
proc ::tcl::clock::EnterLocale { locale oldLocaleVar } {
-
+ if { $locale eq {c} } {
+ return
+ }
upvar 1 $oldLocaleVar oldLocale
variable MsgDir
@@ -2373,18 +2406,18 @@ proc ::tcl::clock::EnterLocale { locale oldLocaleVar } {
# date and time formats from the Control Panel.
# First, load the 'current' locale if it's not yet loaded
- if {![dict exists $McLoaded $oldLocale] } {
+ if {![::tcl::dict::exists $McLoaded $oldLocale] } {
mcload $MsgDir
- dict set McLoaded $oldLocale {}
+ ::tcl::dict::set McLoaded $oldLocale {}
}
# Make a new locale string for the system locale, and
# get the Control Panel information
set locale ${oldLocale}_windows
- if { ![dict exists $McLoaded $locale] } {
+ if { ![::tcl::dict::exists $McLoaded $locale] } {
LoadWindowsDateTimeFormats $locale
- dict set McLoaded $locale {}
+ ::tcl::dict::set McLoaded $locale {}
}
}
}
@@ -2396,9 +2429,9 @@ proc ::tcl::clock::EnterLocale { locale oldLocaleVar } {
} else {
mclocale $locale
}
- if { ![dict exists $McLoaded $locale] } {
+ if { ![::tcl::dict::exists $McLoaded $locale] } {
mcload $MsgDir
- dict set McLoaded $locale {}
+ ::tcl::dict::set McLoaded $locale {}
}
}
@@ -2556,8 +2589,8 @@ proc ::tcl::clock::LocalizeFormat { locale format } {
variable McLoaded
- if { [dict exists $McLoaded $locale FORMAT $format] } {
- return [dict get $McLoaded $locale FORMAT $format]
+ if { [::tcl::dict::exists $McLoaded $locale FORMAT $format] } {
+ return [::tcl::dict::get $McLoaded $locale FORMAT $format]
}
set inFormat $format
@@ -2583,7 +2616,7 @@ proc ::tcl::clock::LocalizeFormat { locale format } {
lappend list %Ec [string map $list [mc LOCALE_DATE_TIME_FORMAT]]
set format [string map $list $format]
- dict set McLoaded $locale FORMAT $inFormat $format
+ ::tcl::dict::set McLoaded $locale FORMAT $inFormat $format
return $format
}
@@ -2650,7 +2683,7 @@ proc ::tcl::clock::FormatStarDate { date } {
# Get day of year, zero based
- set doy [expr { [dict get $date dayOfYear] - 1 }]
+ set doy [expr { [::tcl::dict::get $date dayOfYear] - 1 }]
# Determine whether the year is a leap year
@@ -2667,9 +2700,9 @@ proc ::tcl::clock::FormatStarDate { date } {
# Put together the StarDate
return [::format "Stardate %02d%03d.%1d" \
- [expr { [dict get $date year] - $Roddenberry }] \
+ [expr { [::tcl::dict::get $date year] - $Roddenberry }] \
$fractYear \
- [expr { [dict get $date localSeconds] % 86400
+ [expr { [::tcl::dict::get $date localSeconds] % 86400
/ ( 86400 / 10 ) }]]
}
@@ -2701,7 +2734,7 @@ proc ::tcl::clock::ParseStarDate { year fractYear fractDay } {
# Build a tentative date from year and fraction.
- set date [dict create \
+ set date [::tcl::dict::create \
gregorian 1 \
era CE \
year [expr { $year + $Roddenberry }] \
@@ -2716,17 +2749,17 @@ proc ::tcl::clock::ParseStarDate { year fractYear fractDay } {
# year is a leap year
if { $lp } {
- dict set date dayOfYear \
+ ::tcl::dict::set date dayOfYear \
[expr { $fractYear * 366 / 1000 + 1 }]
} else {
- dict set date dayOfYear \
+ ::tcl::dict::set date dayOfYear \
[expr { $fractYear * 365 / 1000 + 1 }]
}
- dict unset date julianDay
- dict unset date gregorian
+ ::tcl::dict::unset date julianDay
+ ::tcl::dict::unset date gregorian
set date [GetJulianDayFromGregorianEraYearDay $date[set date {}]]
- return [expr { 86400 * [dict get $date julianDay]
+ return [expr { 86400 * [::tcl::dict::get $date julianDay]
- 210866803200
+ ( 86400 / 10 ) * $fractDay }]
@@ -2794,11 +2827,11 @@ proc ::tcl::clock::InterpretTwoDigitYear { date baseTime
{ twoDigitField yearOfCentury }
{ fourDigitField year } } {
- set yr [dict get $date $twoDigitField]
+ set yr [::tcl::dict::get $date $twoDigitField]
if { $yr <= 37 } {
- dict set date $fourDigitField [expr { $yr + 2000 }]
+ ::tcl::dict::set date $fourDigitField [expr { $yr + 2000 }]
} else {
- dict set date $fourDigitField [expr { $yr + 1900 }]
+ ::tcl::dict::set date $fourDigitField [expr { $yr + 1900 }]
}
return $date
@@ -2837,8 +2870,8 @@ proc ::tcl::clock::AssignBaseYear { date baseTime timezone changeover } {
# Store the converted year
- dict set date era [dict get $date2 era]
- dict set date year [dict get $date2 year]
+ ::tcl::dict::set date era [::tcl::dict::get $date2 era]
+ ::tcl::dict::set date year [::tcl::dict::get $date2 year]
return $date
@@ -2877,8 +2910,8 @@ proc ::tcl::clock::AssignBaseIso8601Year {date baseTime timeZone changeover} {
# Calculate the ISO8601 date and transfer the year
- dict set date era CE
- dict set date iso8601Year [dict get $date2 iso8601Year]
+ ::tcl::dict::set date era CE
+ ::tcl::dict::set date iso8601Year [::tcl::dict::get $date2 iso8601Year]
return $date
}
@@ -2911,9 +2944,9 @@ proc ::tcl::clock::AssignBaseMonth {date baseTime timezone changeover} {
# Find the year and month corresponding to the base time
set date2 [GetDateFields $baseTime $TZData($timezone) $changeover]
- dict set date era [dict get $date2 era]
- dict set date year [dict get $date2 year]
- dict set date month [dict get $date2 month]
+ ::tcl::dict::set date era [::tcl::dict::get $date2 era]
+ ::tcl::dict::set date year [::tcl::dict::get $date2 year]
+ ::tcl::dict::set date month [::tcl::dict::get $date2 month]
return $date
}
@@ -2950,9 +2983,9 @@ proc ::tcl::clock::AssignBaseWeek {date baseTime timeZone changeover} {
# Calculate the ISO8601 date and transfer the year
- dict set date era CE
- dict set date iso8601Year [dict get $date2 iso8601Year]
- dict set date iso8601Week [dict get $date2 iso8601Week]
+ ::tcl::dict::set date era CE
+ ::tcl::dict::set date iso8601Year [::tcl::dict::get $date2 iso8601Year]
+ ::tcl::dict::set date iso8601Week [::tcl::dict::get $date2 iso8601Week]
return $date
}
@@ -2984,7 +3017,7 @@ proc ::tcl::clock::AssignBaseJulianDay { date baseTime timeZone changeover } {
# Find the Julian Day Number corresponding to the base time
set date2 [GetDateFields $baseTime $TZData($timeZone) $changeover]
- dict set date julianDay [dict get $date2 julianDay]
+ ::tcl::dict::set date julianDay [::tcl::dict::get $date2 julianDay]
return $date
}
@@ -3009,14 +3042,14 @@ proc ::tcl::clock::AssignBaseJulianDay { date baseTime timeZone changeover } {
proc ::tcl::clock::InterpretHMSP { date } {
- set hr [dict get $date hourAMPM]
+ set hr [::tcl::dict::get $date hourAMPM]
if { $hr == 12 } {
set hr 0
}
- if { [dict get $date amPmIndicator] } {
+ if { [::tcl::dict::get $date amPmIndicator] } {
incr hr 12
}
- dict set date hour $hr
+ ::tcl::dict::set date hour $hr
return [InterpretHMS $date[set date {}]]
}
@@ -3042,9 +3075,9 @@ proc ::tcl::clock::InterpretHMSP { date } {
proc ::tcl::clock::InterpretHMS { date } {
- return [expr { ( [dict get $date hour] * 60
- + [dict get $date minute] ) * 60
- + [dict get $date second] }]
+ return [expr { ( [::tcl::dict::get $date hour] * 60
+ + [::tcl::dict::get $date minute] ) * 60
+ + [::tcl::dict::get $date second] }]
}
@@ -3068,8 +3101,13 @@ proc ::tcl::clock::InterpretHMS { date } {
#----------------------------------------------------------------------
proc ::tcl::clock::GetSystemTimeZone {} {
-
variable CachedSystemTimeZone
+ if { [info exists CachedSystemTimeZone] } {
+ ## if not switched to another time zone (simply check cached every 10 minutes) :
+ if {abs([seconds] - [lindex $CachedSystemTimeZone 1]) < 600} {
+ return [lindex $CachedSystemTimeZone 0]
+ }
+ }
variable TimeZoneBad
if {[set result [getenv TCL_TZ]] ne {}} {
@@ -3080,28 +3118,25 @@ proc ::tcl::clock::GetSystemTimeZone {} {
if {![info exists timezone]} {
# Cache the time zone only if it was detected by one of the
# expensive methods.
- if { [info exists CachedSystemTimeZone] } {
- set timezone $CachedSystemTimeZone
- } elseif { $::tcl_platform(platform) eq {windows} } {
- set timezone [GuessWindowsTimeZone]
- } elseif { [file exists /etc/localtime]
- && ![catch {ReadZoneinfoFile \
- Tcl/Localtime /etc/localtime}] } {
- set timezone :Tcl/Localtime
- } else {
- set timezone :localtime
- }
- set CachedSystemTimeZone $timezone
+ if { $::tcl_platform(platform) eq {windows} } {
+ set timezone [GuessWindowsTimeZone]
+ } elseif { [file exists /etc/localtime]
+ && ![catch {ReadZoneinfoFile \
+ Tcl/Localtime /etc/localtime}] } {
+ set timezone :Tcl/Localtime
+ } else {
+ set timezone :localtime
+ }
}
- if { ![dict exists $TimeZoneBad $timezone] } {
- dict set TimeZoneBad $timezone [catch {SetupTimeZone $timezone}]
+ if { ![::tcl::dict::exists $TimeZoneBad $timezone] } {
+ ::tcl::dict::set TimeZoneBad $timezone [catch {SetupTimeZone $timezone}]
}
- if { [dict get $TimeZoneBad $timezone] } {
- return :localtime
- } else {
- return $timezone
+ if { [::tcl::dict::get $TimeZoneBad $timezone] } {
+ set timezone :localtime
}
-
+ ## cache (simply check cached every 10 minutes (rounded to 00:10:00)):
+ set CachedSystemTimeZone [list $timezone [expr {[set switchtime [seconds]] - ($switchtime % 600)}]]
+ return $timezone
}
#----------------------------------------------------------------------
@@ -3132,11 +3167,11 @@ proc ::tcl::clock::ConvertLegacyTimeZone { tzname } {
variable LegacyTimeZone
set tzname [string tolower $tzname]
- if { ![dict exists $LegacyTimeZone $tzname] } {
+ if { ![::tcl::dict::exists $LegacyTimeZone $tzname] } {
return -code error -errorcode [list CLOCK badTZName $tzname] \
"time zone \"$tzname\" not found"
} else {
- return [dict get $LegacyTimeZone $tzname]
+ return [::tcl::dict::get $LegacyTimeZone $tzname]
}
}
@@ -3212,8 +3247,8 @@ proc ::tcl::clock::SetupTimeZone { timezone } {
# This looks like a POSIX time zone - try to process it
if { [catch {ProcessPosixTimeZone $tzfields} data opts] } {
- if { [lindex [dict get $opts -errorcode] 0] eq {CLOCK} } {
- dict unset opts -errorinfo
+ if { [lindex [::tcl::dict::get $opts -errorcode] 0] eq {CLOCK} } {
+ ::tcl::dict::unset opts -errorinfo
}
return -options $opts $data
} else {
@@ -3227,7 +3262,7 @@ proc ::tcl::clock::SetupTimeZone { timezone } {
if { [catch { LoadTimeZoneFile $timezone }]
&& [catch { LoadZoneinfoFile $timezone } - opts] } {
- dict unset opts -errorinfo
+ ::tcl::dict::unset opts -errorinfo
return -options $opts "time zone $timezone not found"
}
set TZData($timezone) $TZData(:$timezone)
@@ -3307,15 +3342,15 @@ proc ::tcl::clock::GuessWindowsTimeZone {} {
# in an environment (e.g. starpack) where tzdata is incomplete.
# (Bug 1237907)
- if { [dict exists $WinZoneInfo $data] } {
- set tzname [dict get $WinZoneInfo $data]
- if { ! [dict exists $TimeZoneBad $tzname] } {
- dict set TimeZoneBad $tzname [catch {SetupTimeZone $tzname}]
+ if { [::tcl::dict::exists $WinZoneInfo $data] } {
+ set tzname [::tcl::dict::get $WinZoneInfo $data]
+ if { ! [::tcl::dict::exists $TimeZoneBad $tzname] } {
+ ::tcl::dict::set TimeZoneBad $tzname [catch {SetupTimeZone $tzname}]
}
} else {
set tzname {}
}
- if { $tzname eq {} || [dict get $TimeZoneBad $tzname] } {
+ if { $tzname eq {} || [::tcl::dict::get $TimeZoneBad $tzname] } {
lassign $data \
bias stdBias dstBias \
stdYear stdMonth stdDayOfWeek stdDayOfMonth \
@@ -3377,10 +3412,10 @@ proc ::tcl::clock::GuessWindowsTimeZone {} {
: [::format %02d $stdMinute] \
: [::format %02d $stdSecond]
}
- dict set WinZoneInfo $data $tzname
+ ::tcl::dict::set WinZoneInfo $data $tzname
}
- return [dict get $WinZoneInfo $data]
+ return [::tcl::dict::get $WinZoneInfo $data]
}
@@ -3585,7 +3620,7 @@ proc ::tcl::clock::ReadZoneinfoFile {fileName fname} {
set abbrevs {}
foreach a $abbrList {
for {set j 0} {$j <= [string length $a]} {incr j} {
- dict set abbrevs $i [string range $a $j end]
+ ::tcl::dict::set abbrevs $i [string range $a $j end]
incr i
}
}
@@ -3601,7 +3636,7 @@ proc ::tcl::clock::ReadZoneinfoFile {fileName fname} {
}
set lastTime $t
lassign [lindex $types $c] gmtoff isDst abbrInd
- set abbrev [dict get $abbrevs $abbrInd]
+ set abbrev [::tcl::dict::get $abbrevs $abbrInd]
lappend r [list $t $gmtoff $isDst $abbrev]
}
@@ -3836,23 +3871,23 @@ proc ::tcl::clock::ProcessPosixTimeZone { z } {
# Determine the standard time zone name and seconds east of Greenwich
- set stdName [dict get $z stdName]
+ set stdName [::tcl::dict::get $z stdName]
if { [string index $stdName 0] eq {<} } {
set stdName [string range $stdName 1 end-1]
}
- if { [dict get $z stdSignum] eq {-} } {
+ if { [::tcl::dict::get $z stdSignum] eq {-} } {
set stdSignum +1
} else {
set stdSignum -1
}
- set stdHours [lindex [::scan [dict get $z stdHours] %d] 0]
- if { [dict get $z stdMinutes] ne {} } {
- set stdMinutes [lindex [::scan [dict get $z stdMinutes] %d] 0]
+ set stdHours [lindex [::scan [::tcl::dict::get $z stdHours] %d] 0]
+ if { [::tcl::dict::get $z stdMinutes] ne {} } {
+ set stdMinutes [lindex [::scan [::tcl::dict::get $z stdMinutes] %d] 0]
} else {
set stdMinutes 0
}
- if { [dict get $z stdSeconds] ne {} } {
- set stdSeconds [lindex [::scan [dict get $z stdSeconds] %d] 0]
+ if { [::tcl::dict::get $z stdSeconds] ne {} } {
+ set stdSeconds [lindex [::scan [::tcl::dict::get $z stdSeconds] %d] 0]
} else {
set stdSeconds 0
}
@@ -3863,7 +3898,7 @@ proc ::tcl::clock::ProcessPosixTimeZone { z } {
# If there's no daylight zone, we're done
- set dstName [dict get $z dstName]
+ set dstName [::tcl::dict::get $z dstName]
if { $dstName eq {} } {
return $data
}
@@ -3873,22 +3908,22 @@ proc ::tcl::clock::ProcessPosixTimeZone { z } {
# Determine the daylight name
- if { [dict get $z dstSignum] eq {-} } {
+ if { [::tcl::dict::get $z dstSignum] eq {-} } {
set dstSignum +1
} else {
set dstSignum -1
}
- if { [dict get $z dstHours] eq {} } {
+ if { [::tcl::dict::get $z dstHours] eq {} } {
set dstOffset [expr { 3600 + $stdOffset }]
} else {
- set dstHours [lindex [::scan [dict get $z dstHours] %d] 0]
- if { [dict get $z dstMinutes] ne {} } {
- set dstMinutes [lindex [::scan [dict get $z dstMinutes] %d] 0]
+ set dstHours [lindex [::scan [::tcl::dict::get $z dstHours] %d] 0]
+ if { [::tcl::dict::get $z dstMinutes] ne {} } {
+ set dstMinutes [lindex [::scan [::tcl::dict::get $z dstMinutes] %d] 0]
} else {
set dstMinutes 0
}
- if { [dict get $z dstSeconds] ne {} } {
- set dstSeconds [lindex [::scan [dict get $z dstSeconds] %d] 0]
+ if { [::tcl::dict::get $z dstSeconds] ne {} } {
+ set dstSeconds [lindex [::scan [::tcl::dict::get $z dstSeconds] %d] 0]
} else {
set dstSeconds 0
}
@@ -3903,46 +3938,46 @@ proc ::tcl::clock::ProcessPosixTimeZone { z } {
# US end time is the first Sunday in November.
# EU end time is the last Sunday in October
- if { [dict get $z startDayOfYear] eq {}
- && [dict get $z startMonth] eq {} } {
+ if { [::tcl::dict::get $z startDayOfYear] eq {}
+ && [::tcl::dict::get $z startMonth] eq {} } {
if {($stdSignum * $stdHours>=0) && ($stdSignum * $stdHours<=12)} {
# EU
- dict set z startWeekOfMonth 5
+ ::tcl::dict::set z startWeekOfMonth 5
if {$stdHours>2} {
- dict set z startHours 2
+ ::tcl::dict::set z startHours 2
} else {
- dict set z startHours [expr {$stdHours+1}]
+ ::tcl::dict::set z startHours [expr {$stdHours+1}]
}
} else {
# US
- dict set z startWeekOfMonth 2
- dict set z startHours 2
+ ::tcl::dict::set z startWeekOfMonth 2
+ ::tcl::dict::set z startHours 2
}
- dict set z startMonth 3
- dict set z startDayOfWeek 0
- dict set z startMinutes 0
- dict set z startSeconds 0
+ ::tcl::dict::set z startMonth 3
+ ::tcl::dict::set z startDayOfWeek 0
+ ::tcl::dict::set z startMinutes 0
+ ::tcl::dict::set z startSeconds 0
}
- if { [dict get $z endDayOfYear] eq {}
- && [dict get $z endMonth] eq {} } {
+ if { [::tcl::dict::get $z endDayOfYear] eq {}
+ && [::tcl::dict::get $z endMonth] eq {} } {
if {($stdSignum * $stdHours>=0) && ($stdSignum * $stdHours<=12)} {
# EU
- dict set z endMonth 10
- dict set z endWeekOfMonth 5
+ ::tcl::dict::set z endMonth 10
+ ::tcl::dict::set z endWeekOfMonth 5
if {$stdHours>2} {
- dict set z endHours 3
+ ::tcl::dict::set z endHours 3
} else {
- dict set z endHours [expr {$stdHours+2}]
+ ::tcl::dict::set z endHours [expr {$stdHours+2}]
}
} else {
# US
- dict set z endMonth 11
- dict set z endWeekOfMonth 1
- dict set z endHours 2
+ ::tcl::dict::set z endMonth 11
+ ::tcl::dict::set z endWeekOfMonth 1
+ ::tcl::dict::set z endHours 2
}
- dict set z endDayOfWeek 0
- dict set z endMinutes 0
- dict set z endSeconds 0
+ ::tcl::dict::set z endDayOfWeek 0
+ ::tcl::dict::set z endMinutes 0
+ ::tcl::dict::set z endSeconds 0
}
# Put DST in effect in all years from 1916 to 2099.
@@ -3993,51 +4028,51 @@ proc ::tcl::clock::DeterminePosixDSTTime { z bound y } {
# Determine the start or end day of DST
- set date [dict create era CE year $y]
- set doy [dict get $z ${bound}DayOfYear]
+ set date [::tcl::dict::create era CE year $y]
+ set doy [::tcl::dict::get $z ${bound}DayOfYear]
if { $doy ne {} } {
# Time was specified as a day of the year
- if { [dict get $z ${bound}J] ne {}
+ if { [::tcl::dict::get $z ${bound}J] ne {}
&& [IsGregorianLeapYear $y]
&& ( $doy > $FEB_28 ) } {
incr doy
}
- dict set date dayOfYear $doy
+ ::tcl::dict::set date dayOfYear $doy
set date [GetJulianDayFromEraYearDay $date[set date {}] 2361222]
} else {
# Time was specified as a day of the week within a month
- dict set date month [dict get $z ${bound}Month]
- dict set date dayOfWeek [dict get $z ${bound}DayOfWeek]
- set dowim [dict get $z ${bound}WeekOfMonth]
+ ::tcl::dict::set date month [::tcl::dict::get $z ${bound}Month]
+ ::tcl::dict::set date dayOfWeek [::tcl::dict::get $z ${bound}DayOfWeek]
+ set dowim [::tcl::dict::get $z ${bound}WeekOfMonth]
if { $dowim >= 5 } {
set dowim -1
}
- dict set date dayOfWeekInMonth $dowim
+ ::tcl::dict::set date dayOfWeekInMonth $dowim
set date [GetJulianDayFromEraYearMonthWeekDay $date[set date {}] 2361222]
}
- set jd [dict get $date julianDay]
+ set jd [::tcl::dict::get $date julianDay]
set seconds [expr { wide($jd) * wide(86400)
- wide(210866803200) }]
- set h [dict get $z ${bound}Hours]
+ set h [::tcl::dict::get $z ${bound}Hours]
if { $h eq {} } {
set h 2
} else {
set h [lindex [::scan $h %d] 0]
}
- set m [dict get $z ${bound}Minutes]
+ set m [::tcl::dict::get $z ${bound}Minutes]
if { $m eq {} } {
set m 0
} else {
set m [lindex [::scan $m %d] 0]
}
- set s [dict get $z ${bound}Seconds]
+ set s [::tcl::dict::get $z ${bound}Seconds]
if { $s eq {} } {
set s 0
} else {
@@ -4070,15 +4105,15 @@ proc ::tcl::clock::DeterminePosixDSTTime { z bound y } {
proc ::tcl::clock::GetLocaleEra { date etable } {
- set index [BSearch $etable [dict get $date localSeconds]]
+ set index [BSearch $etable [::tcl::dict::get $date localSeconds]]
if { $index < 0} {
- dict set date localeEra \
- [::format %02d [expr { [dict get $date year] / 100 }]]
- dict set date localeYear \
- [expr { [dict get $date year] % 100 }]
+ ::tcl::dict::set date localeEra \
+ [::format %02d [expr { [::tcl::dict::get $date year] / 100 }]]
+ ::tcl::dict::set date localeYear \
+ [expr { [::tcl::dict::get $date year] % 100 }]
} else {
- dict set date localeEra [lindex $etable $index 1]
- dict set date localeYear [expr { [dict get $date year]
+ ::tcl::dict::set date localeEra [lindex $etable $index 1]
+ ::tcl::dict::set date localeYear [expr { [::tcl::dict::get $date year]
- [lindex $etable $index 2] }]
}
return $date
@@ -4117,21 +4152,21 @@ proc ::tcl::clock::GetJulianDayFromEraYearDay {date changeover} {
# Get absolute year number from the civil year
- switch -exact -- [dict get $date era] {
+ switch -exact -- [::tcl::dict::get $date era] {
BCE {
- set year [expr { 1 - [dict get $date year] }]
+ set year [expr { 1 - [::tcl::dict::get $date year] }]
}
CE {
- set year [dict get $date year]
+ set year [::tcl::dict::get $date year]
}
}
set ym1 [expr { $year - 1 }]
# Try the Gregorian calendar first.
- dict set date gregorian 1
+ ::tcl::dict::set date gregorian 1
set jd [expr { 1721425
- + [dict get $date dayOfYear]
+ + [::tcl::dict::get $date dayOfYear]
+ ( 365 * $ym1 )
+ ( $ym1 / 4 )
- ( $ym1 / 100 )
@@ -4140,14 +4175,14 @@ proc ::tcl::clock::GetJulianDayFromEraYearDay {date changeover} {
# If the date is before the Gregorian change, use the Julian calendar.
if { $jd < $changeover } {
- dict set date gregorian 0
+ ::tcl::dict::set date gregorian 0
set jd [expr { 1721423
- + [dict get $date dayOfYear]
+ + [::tcl::dict::get $date dayOfYear]
+ ( 365 * $ym1 )
+ ( $ym1 / 4 ) }]
}
- dict set date julianDay $jd
+ ::tcl::dict::set date julianDay $jd
return $date
}
@@ -4181,18 +4216,18 @@ proc ::tcl::clock::GetJulianDayFromEraYearMonthWeekDay {date changeover} {
# following month (dayOfWeekInMonth < 0)
set date2 $date
- set week [dict get $date dayOfWeekInMonth]
+ set week [::tcl::dict::get $date dayOfWeekInMonth]
if { $week >= 0 } {
- dict set date2 dayOfMonth 0
+ ::tcl::dict::set date2 dayOfMonth 0
} else {
- dict incr date2 month
- dict set date2 dayOfMonth 7
+ ::tcl::dict::incr date2 month
+ ::tcl::dict::set date2 dayOfMonth 7
}
set date2 [GetJulianDayFromEraYearMonthDay $date2[set date2 {}] \
$changeover]
- set wd0 [WeekdayOnOrBefore [dict get $date dayOfWeek] \
- [dict get $date2 julianDay]]
- dict set date julianDay [expr { $wd0 + 7 * $week }]
+ set wd0 [WeekdayOnOrBefore [::tcl::dict::get $date dayOfWeek] \
+ [::tcl::dict::get $date2 julianDay]]
+ ::tcl::dict::set date julianDay [expr { $wd0 + 7 * $week }]
return $date
}
@@ -4218,17 +4253,17 @@ proc ::tcl::clock::GetJulianDayFromEraYearMonthWeekDay {date changeover} {
proc ::tcl::clock::IsGregorianLeapYear { date } {
- switch -exact -- [dict get $date era] {
+ switch -exact -- [::tcl::dict::get $date era] {
BCE {
- set year [expr { 1 - [dict get $date year]}]
+ set year [expr { 1 - [::tcl::dict::get $date year]}]
}
CE {
- set year [dict get $date year]
+ set year [::tcl::dict::get $date year]
}
}
if { $year % 4 != 0 } {
return 0
- } elseif { ![dict get $date gregorian] } {
+ } elseif { ![::tcl::dict::get $date gregorian] } {
return 1
} elseif { $year % 400 == 0 } {
return 1
@@ -4426,12 +4461,14 @@ proc ::tcl::clock::add { clockval args } {
}
}
- EnterLocale $locale oldLocale
+ if { $locale ne {c} && $locale ne [mclocale] } {
+ EnterLocale $locale oldLocale
+ }
set changeover [mc GREGORIAN_CHANGE_DATE]
if {[catch {SetupTimeZone $timezone} retval opts]} {
- dict unset opts -errorinfo
+ ::tcl::dict::unset opts -errorinfo
return -options $opts $retval
}
@@ -4488,8 +4525,8 @@ proc ::tcl::clock::add { clockval args } {
}
if { $status == 1 } {
- if { [lindex [dict get $opts -errorcode] 0] eq {CLOCK} } {
- dict unset opts -errorinfo
+ if { [lindex [::tcl::dict::get $opts -errorcode] 0] eq {CLOCK} } {
+ ::tcl::dict::unset opts -errorinfo
}
return -options $opts $result
} else {
@@ -4528,19 +4565,19 @@ proc ::tcl::clock::AddMonths { months clockval timezone changeover } {
# Convert the time to year, month, day, and fraction of day.
set date [GetDateFields $clockval $TZData($timezone) $changeover]
- dict set date secondOfDay [expr { [dict get $date localSeconds]
+ ::tcl::dict::set date secondOfDay [expr { [::tcl::dict::get $date localSeconds]
% 86400 }]
- dict set date tzName $timezone
+ ::tcl::dict::set date tzName $timezone
# Add the requisite number of months
- set m [dict get $date month]
+ set m [::tcl::dict::get $date month]
incr m $months
incr m -1
set delta [expr { $m / 12 }]
set mm [expr { $m % 12 }]
- dict set date month [expr { $mm + 1 }]
- dict incr date year $delta
+ ::tcl::dict::set date month [expr { $mm + 1 }]
+ ::tcl::dict::incr date year $delta
# If the date doesn't exist in the current month, repair it
@@ -4549,8 +4586,8 @@ proc ::tcl::clock::AddMonths { months clockval timezone changeover } {
} else {
set hath [lindex $DaysInRomanMonthInCommonYear $mm]
}
- if { [dict get $date dayOfMonth] > $hath } {
- dict set date dayOfMonth $hath
+ if { [::tcl::dict::get $date dayOfMonth] > $hath } {
+ ::tcl::dict::set date dayOfMonth $hath
}
# Reconvert to a number of seconds
@@ -4558,14 +4595,14 @@ proc ::tcl::clock::AddMonths { months clockval timezone changeover } {
set date [GetJulianDayFromEraYearMonthDay \
$date[set date {}]\
$changeover]
- dict set date localSeconds \
+ ::tcl::dict::set date localSeconds \
[expr { -210866803200
- + ( 86400 * wide([dict get $date julianDay]) )
- + [dict get $date secondOfDay] }]
+ + ( 86400 * wide([::tcl::dict::get $date julianDay]) )
+ + [::tcl::dict::get $date secondOfDay] }]
set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) \
$changeover]
- return [dict get $date seconds]
+ return [::tcl::dict::get $date seconds]
}
@@ -4599,24 +4636,24 @@ proc ::tcl::clock::AddDays { days clockval timezone changeover } {
# Convert the time to Julian Day
set date [GetDateFields $clockval $TZData($timezone) $changeover]
- dict set date secondOfDay [expr { [dict get $date localSeconds]
+ ::tcl::dict::set date secondOfDay [expr { [::tcl::dict::get $date localSeconds]
% 86400 }]
- dict set date tzName $timezone
+ ::tcl::dict::set date tzName $timezone
# Add the requisite number of days
- dict incr date julianDay $days
+ ::tcl::dict::incr date julianDay $days
# Reconvert to a number of seconds
- dict set date localSeconds \
+ ::tcl::dict::set date localSeconds \
[expr { -210866803200
- + ( 86400 * wide([dict get $date julianDay]) )
- + [dict get $date secondOfDay] }]
+ + ( 86400 * wide([::tcl::dict::get $date julianDay]) )
+ + [::tcl::dict::get $date secondOfDay] }]
set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) \
$changeover]
- return [dict get $date seconds]
+ return [::tcl::dict::get $date seconds]
}
@@ -4644,11 +4681,11 @@ proc ::tcl::clock::AddDays { days clockval timezone changeover } {
proc ::tcl::clock::mc { name } {
variable McLoaded
set Locale [mclocale]
- if { [dict exists $McLoaded $Locale $name] } {
- return [dict get $McLoaded $Locale $name]
+ if { [::tcl::dict::exists $McLoaded $Locale $name] } {
+ return [::tcl::dict::get $McLoaded $Locale $name]
} else {
set val [::msgcat::mc $name]
- dict set McLoaded $Locale $name $val
+ ::tcl::dict::set McLoaded $Locale $name $val
return $val
}
}
@@ -4673,6 +4710,7 @@ proc ::tcl::clock::mc { name } {
proc ::tcl::clock::ClearCaches {} {
variable FormatProc
+ variable ScanProc
variable LocaleNumeralCache
variable McLoaded
variable CachedSystemTimeZone
@@ -4686,6 +4724,7 @@ proc ::tcl::clock::ClearCaches {} {
}
catch {unset FormatProc}
+ catch {unset ScanProc}
set LocaleNumeralCache {}
set McLoaded {}
catch {unset CachedSystemTimeZone}
@@ -4693,3 +4732,209 @@ proc ::tcl::clock::ClearCaches {} {
InitTZData
}
+
+
+#----------------------------------------------------------------------
+# [SB] extension:
+# - validate :
+# - create date direct from args (without parsing string) :
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ValidDate {date string} {
+ ## check date :
+ if {[::tcl::dict::exists $date month] && [::tcl::dict::exists $date dayOfMonth]} {
+ ## first - month :
+ if { [set month [::tcl::dict::get $date month]] > 12 || $month < 1 } {
+ return -code error -errorcode [list CLOCK invalidArgs] "unable to convert date-time string \"$string\": invalid month"
+ }
+ ## by february check leap year :
+ if {[set day [::tcl::dict::get $date dayOfMonth]] < 1} {
+ return -code error -errorcode [list CLOCK invalidArgs] "unable to convert date-time string \"$string\": invalid day"
+ }
+ if {$day > 28} {
+ if {$month == 2} {
+ if {[::tcl::dict::exists $date gregorian]} {
+ if { [IsGregorianLeapYear $date] } {
+ variable DaysInRomanMonthInLeapYear
+ set hath [lindex $DaysInRomanMonthInLeapYear [expr {$month - 1}]]
+ } else {
+ variable DaysInRomanMonthInCommonYear
+ set hath [lindex $DaysInRomanMonthInCommonYear [expr {$month - 1}]]
+ }
+ }
+ } else {
+ variable DaysInRomanMonthInCommonYear
+ set hath [lindex $DaysInRomanMonthInCommonYear [expr {$month - 1}]]
+ }
+ ## check day in month :
+ if { $day > $hath } {
+ return -code error -errorcode [list CLOCK invalidArgs] "unable to convert date-time string \"$string\": invalid day"
+ }
+ }
+ }
+ ## Oldscan could returns secondOfDay (parsedTime) -1 by invalid time (ex.: 25:00:00) :
+ if {[::tcl::dict::exists $date secondOfDay] && [::tcl::dict::get $date secondOfDay] == -1} {
+ return -code error -errorcode [list CLOCK invalidArgs] "unable to convert date-time string \"$string\": invalid time"
+ }
+ ## check time (00:00:00 - 23:59:59 or 00:00:00[ap]m - 12:00:00[ap]m) :
+ if {[::tcl::dict::exists $date hour]} {
+ if {[set v [::tcl::dict::get $date hour]] < 0 || $v > 23} {
+ return -code error -errorcode [list CLOCK invalidArgs] "unable to convert date-time string \"$string\": invalid time (hour)"
+ }
+ if {[::tcl::dict::exists $date amPmIndicator] && $v > 12} {
+ return -code error -errorcode [list CLOCK invalidArgs] "unable to convert date-time string \"$string\": invalid time (hour/am:pm)"
+ }
+ }
+ if {[::tcl::dict::exists $date minute] && ([set v [::tcl::dict::get $date minute]] < 0 || $v > 59)} {
+ return -code error -errorcode [list CLOCK invalidArgs] "unable to convert date-time string \"$string\": invalid time (minute)"
+ }
+ if {[::tcl::dict::exists $date second] && ([set v [::tcl::dict::get $date second]] < 0 || $v > 59)} {
+ return -code error -errorcode [list CLOCK invalidArgs] "unable to convert date-time string \"$string\": invalid time (second)"
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::MakeDate {args} {
+ set date $args[set args {}]
+
+ if {![::tcl::dict::exists $date baseTime]} {
+ set baseTime [clock seconds]
+ } else {
+ set baseTime [::tcl::dict::get $date baseTime]
+ }
+
+ set changeover 2361222; #[tcl::clock::mc GREGORIAN_CHANGE_DATE]
+ set tz {}
+ if {[::tcl::dict::exists $date tzName]} {
+ set tz [::tcl::dict::get $date tzName]
+ if {$tz == {}} {
+ set tz [::tcl::clock::GetSystemTimeZone]
+ } elseif {$tz in {:UTC :GMT}} {
+ set tz {}
+ }
+ if {$tz != {}} {
+ variable TZData
+ if {![info exists TZData($tz)]} {
+ ::tcl::clock::SetupTimeZone $tz
+ }
+ }
+ }
+
+ ::tcl::dict::set date era CE
+ # Julian Day Number from the fields.
+ if {![::tcl::dict::exists $date year]} {
+ if {![::tcl::dict::exists $date yearOfCentury]} {
+ set date [AssignBaseYear $date[set date {}] \
+ $baseTime $tz $changeover]
+ } else {
+ set date [InterpretTwoDigitYear $date[set date {}] $baseTime]
+ }
+ }
+ if {![::tcl::dict::exists $date month]} {
+ set date [AssignBaseMonth $date[set date {}] \
+ $baseTime $tz $changeover]
+ }
+ if {![::tcl::dict::exists $date dayOfMonth]} {
+ variable TZData
+ set date2 [GetDateFields $baseTime $TZData($tz) $changeover]
+ ::tcl::dict::set date dayOfMonth [::tcl::dict::get $date2 dayOfMonth]
+ }
+ if {[catch {
+ set date [::tcl::clock::GetJulianDayFromEraYearMonthDay $date[set date {}] $changeover]
+ } msg]} {
+ return -code error -errorcode [list CLOCK invalidArgs] $msg
+ }
+ # Get time of day
+ ::tcl::dict::set date secondOfDay [::tcl::clock::InterpretHMS $date]
+ # Assemble seconds, and convert local nominal time to UTC.
+ if { [::tcl::dict::get $date julianDay] > 5373484 } {
+ return -code error -errorcode [list CLOCK dateTooLarge] "requested date too large to represent"
+ }
+ ::tcl::dict::set date localSeconds [set secs [expr { -210866803200
+ + ( 86400 * wide([::tcl::dict::get $date julianDay]) )
+ + [::tcl::dict::get $date secondOfDay] }]]
+ if {$tz != {}} {
+ set date [::tcl::clock::ConvertLocalToUTC $date[set date {}] $TZData($tz) $changeover]
+ return $date
+ }
+ # set seconds to localSeconds
+ ::tcl::dict::set date seconds $secs
+ return $date
+}
+
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ConvertToSeconds {Y m d H M S {tz {}}} {
+ set date [list \
+ year $Y \
+ month $m \
+ dayOfMonth $d \
+ hour $H \
+ minute $M \
+ second $S \
+ ]
+
+ set changeover 2361222; #[tcl::clock::mc GREGORIAN_CHANGE_DATE]
+ if {$tz == {}} {
+ set tz [GetSystemTimeZone]
+ } elseif {$tz ni {:UTC :GMT}} {
+ variable TZData
+ if {![info exists TZData($tz)]} {
+ SetupTimeZone $tz
+ }
+ } else {
+ ## don't convert in local :
+ set tz {}
+ }
+
+ ::tcl::dict::set date era CE
+ # Julian Day Number from the fields.
+ if {[catch {
+ set date [GetJulianDayFromEraYearMonthDay $date[set date {}] $changeover]
+ } msg]} {
+ return -code error -errorcode [list CLOCK invalidArgs] $msg
+ }
+ # Get time of day
+ ::tcl::dict::set date secondOfDay [InterpretHMS $date]
+ # Assemble seconds, and convert local nominal time to UTC.
+ if { [::tcl::dict::get $date julianDay] > 5373484 } {
+ return -code error -errorcode [list CLOCK dateTooLarge] "requested date too large to represent"
+ }
+ set secs [expr { -210866803200
+ + ( 86400 * wide([::tcl::dict::get $date julianDay]) )
+ + [::tcl::dict::get $date secondOfDay] }]
+ if {$tz != {}} {
+ variable TZData
+ ::tcl::dict::set date localSeconds $secs
+ set date [ConvertLocalToUTC $date[set date {}] $TZData($tz) $changeover]
+ # return utc :
+ return [::tcl::dict::get $date seconds]
+ }
+ # return localSeconds (already utc)
+ return $secs
+}
+
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ConvertFromSeconds {clock {tz {}}} {
+ variable TZData
+
+ set changeover 2361222; #[tcl::clock::mc GREGORIAN_CHANGE_DATE]
+ if {$tz == {}} {
+ set tz [GetSystemTimeZone]
+ } elseif {$tz ni {:UTC :GMT}} {
+ if {![info exists TZData($tz)]} {
+ SetupTimeZone $tz
+ }
+ }
+ ## get date var :
+ set date [GetDateFields $clock $TZData($tz) $changeover]
+ set time [::tcl::dict::get $date localSeconds]
+ ## return list Y m d H M S
+ list \
+ [::tcl::dict::get $date year] [::tcl::dict::get $date month] [::tcl::dict::get $date dayOfMonth] \
+ [expr {$time / 3600 % 24}] [expr {$time / 60 % 60}] [expr {$time % 60}]
+}
+
+#----------------------------------------------------------------------