Browse Source

tidy up API for punk::timeinterval, adjust winlibreoffice to match

master
Julian Noble 3 weeks ago
parent
commit
72648be984
  1. 119
      src/modules/punk/timeinterval-999999.0a1.0.tm
  2. 7
      src/modules/winlibreoffice-999999.0a1.0.tm

119
src/modules/punk/timeinterval-999999.0a1.0.tm

@ -16,7 +16,7 @@
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements
##e.g package require frobz
package require punk::args
@ -46,27 +46,31 @@ namespace eval punk::timeinterval {
#}
namespace export difference
#wrap in dict
proc difference {s1 s2} {
lassign [interval_ymdhs $s1 $s2] Y M D h m s
return [dict create years $Y months $M days $D hours $h minutes $m seconds $s]
}
lappend PUNKARGS [list {
@id -id "::punk::timeinterval::interval_ymdhs"
@cmd -name "punk::timeinterval::interval_ymdhs" -help\
"interval_ymdhs calculates the interval of time between
@id -id "::punk::timeinterval::difference"
@cmd -name "punk::timeinterval::difference" -help\
"difference calculates the interval of time between
the earliest date and the last date
by starting to count at the earliest date."
by starting to count at the earliest date.
It returns a dictionary with keys:
years months days hours minutes seconds"
@opts
-maxunit -default years -choices {years months days hours minutes seconds}
-timezone -default ""
-maxunit -default years -choices {years months days hours minutes seconds} -help\
"If maxunit is specified, the resulting dict will still contain all keys,
but keys for larger units will be zero.
e.g when -maxunit is months, years will be zero but months could be
something like 36.
"
-timezone -default "" -help\
"If unspecified, the timezone will be the
current time zone on the system"
@values -min 2 -max 2
s1
s2
}]
proc interval_ymdhs {args} {
set argd [punk::args::parse $args withid ::punk::timeinterval::interval_ymdhs]
proc difference {args} {
set argd [punk::args::parse $args withid ::punk::timeinterval::difference]
lassign [dict values $argd] leaders opts values received
set maxunit [dict get $opts -maxunit]
set timezone [dict get $opts -timezone]
@ -178,7 +182,7 @@ namespace eval punk::timeinterval {
# Sometimes h = 24, yet is already included as a day!
# For example, this case:
# interval_ymdhs 20010410T000000 19570613T000000
# difference 20010410T000000 19570613T000000
# from Age() example in PostgreSQL documentation:
# http://www.postgresql.org/docs/9.1/static/functions-datetime.html
# psql test=# select age(timestamp '2001-04-10', timestamp '1957-06-13');
@ -224,7 +228,7 @@ namespace eval punk::timeinterval {
# Sanity check: if 60 minutes, push it up to an hour unit
if { $mm >= 60 } {
# adjust 60 minutes to 1 hour
# puts "interval_ymdhs: debug info mm - 60, h + 1"
# puts "difference: debug info mm - 60, h + 1"
set mm [expr { $mm - 60 } ]
incr h
set mm_correction_p 1
@ -248,100 +252,90 @@ namespace eval punk::timeinterval {
}
}
set return_list [list $y $m $d $h $mm $s]
#set return_list [list $y $m $d $h $mm $s]
set return_list [dict create years $y months $m days $d hours $h minutes $mm seconds $s]
# test results by adding difference to s1 to get s2:
set i 0
#set s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"]
set signs_inconsistent_p 0
set diffterms [list]
foreach unit {years months days hours minutes seconds} {
set t_term [lindex $return_list $i]
if { $t_term != 0 } {
dict for {unit t_term} $return_list {
if {$t_term != 0} {
if { $t_term > 0 } {
#append s1_test " +$t_term $unit"
lappend diffterms +$t_term $unit
} else {
#append s1_test " -[expr { abs( $t_term ) } ] $unit"
lappend diffterms -[expr { abs( $t_term ) }] $unit
set signs_inconsistent_p 1
}
}
incr i
}
#set s2_test [clock scan $s1_test]
set s2_test [clock add $s1 {*}$diffterms -timezone $timezone]
# puts "test s2 '$s2_test' from: '$s1_test'"
set counter 0
# puts "test s2 '$s2_test' from: '$s1_test'"
set counter 0
while { $s2 ne $s2_test && $counter < 30 } {
set s2_diff [expr { $s2_test - $s2 } ]
puts "\ninterval_ymdhs: debug s1 $s1 s2 $s2 y $y m $m d $d h $h s $s s2_diff $s2_diff"
puts "difference: debug s1 $s1 s2 $s2 y $y m $m d $d h $h s $s s2_diff $s2_diff"
set absdiff [expr {abs($s2_diff)}]
if { $absdiff > 86399 } {
if { $s2_diff > 0 } {
incr d -1
puts "interval_ymdhs: debug, audit adjustment. decreasing 1 day to $d"
puts "difference: debug, audit adjustment. decreasing 1 day to $d"
} else {
incr d
puts "interval_ymdhs: debug, audit adjustment. increasing 1 day to $d"
puts "difference: debug, audit adjustment. increasing 1 day to $d"
}
} elseif { $absdiff > 3599 } {
if { $s2_diff > 0 } {
incr h -1
puts "interval_ymdhs: debug, audit adjustment. decreasing 1 hour to $h"
puts "difference: debug, audit adjustment. decreasing 1 hour to $h"
} else {
incr h
puts "interval_ymdhs: debug, audit adjustment. increasing 1 hour to $h"
puts "difference: debug, audit adjustment. increasing 1 hour to $h"
}
} elseif { $absdiff > 59 } {
if { $s2_diff > 0 } {
incr mm -1
puts "interval_ymdhs: debug, audit adjustment. decreasing 1 minute to $mm"
puts "difference: debug, audit adjustment. decreasing 1 minute to $mm"
} else {
incr mm
puts "interval_ymdhs: debug, audit adjustment. increasing 1 minute to $mm"
puts "difference: debug, audit adjustment. increasing 1 minute to $mm"
}
} elseif { $absdiff > 0 } {
if { $s2_diff > 0 } {
incr s -1
puts "interval_ymdhs: debug, audit adjustment. decreasing 1 second to $s"
puts "difference: debug, audit adjustment. decreasing 1 second to $s"
} else {
incr s
puts "interval_ymdhs: debug, audit adjustment. increasing 1 second to $s"
puts "difference: debug, audit adjustment. increasing 1 second to $s"
}
}
set return_list [list $y $m $d $h $mm $s]
set return_list [dict create years $y months $m days $d hours $h minutes $mm seconds $s]
# set return_list [list [expr { abs($y) } ] [expr { abs($m) } ] [expr { abs($d) } ] [expr { abs($h) } ] [expr { abs($mm) } ] [expr { abs($s) } ]]
# test results by adding difference to s1 to get s2:
set i 0
#set s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"]
set diffterms [list]
foreach unit {years months days hours minutes seconds} {
set t_term [lindex $return_list $i]
dict for {unit t_term} $return_list {
if { $t_term != 0 } {
if { $t_term > 0 } {
#append s1_test " +$t_term $unit"
lappend diffterms +$t_term $unit
} else {
#append s1_test " -[expr { abs( $t_term ) } ] $unit"
lappend diffterms -[expr { abs( $t_term ) }] $unit
}
}
incr i
}
#set s2_test [clock scan $s1_test]
set s2_test [clock add $s1 {*}$diffterms -timezone $timezone]
incr counter
}
if { ( $counter > 0 || $signs_inconsistent_p ) && ( $h_correction_p || $mm_correction_p || $s_correction_p ) } {
# puts "interval_ymdhs: Corrections in the main calculation were applied: h ${h_correction_p}, mm ${mm_correction_p}, s ${s_correction_p}"
}
#if { ( $counter > 0 || $signs_inconsistent_p ) && ( $h_correction_p || $mm_correction_p || $s_correction_p ) } {
# puts "difference: Corrections in the main calculation were applied: h ${h_correction_p}, mm ${mm_correction_p}, s ${s_correction_p}"
#}
if { $signs_inconsistent_p } {
puts "\ninterval_ymdhs: signs inconsistent y $y m $m d $d h $h mm $mm s $s"
puts "\punk::timeinterval::difference - signs inconsistent y $y m $m d $d h $h mm $mm s $s"
}
if { $s2 eq $s2_test } {
return $return_list
@ -349,23 +343,19 @@ namespace eval punk::timeinterval {
set s2_diff [expr { $s2_test - $s2 } ]
puts "debug s1 $s1 s1_p1 $s1_p1 s1_p2 $s1_p2 s1_p3 $s1_p3 s1_p4 $s1_p4"
puts "debug y $y m $m d $d h $h mm $mm s $s"
puts "interval_ymdhs error: s2 is '$s2' but s2_test is '$s2_test' a difference of ${s2_diff} from s1 '$s1_test'."
# error "result audit fails" "error: s2 is $s2 but s2_test is '$s2_test' a difference of ${s2_diff} from: '$s1_test'."
puts "punk::timeinterval::difference - error: s2 is '$s2' but s2_test is '$s2_test' a difference of ${s2_diff} from s1 '$s1_test'."
error "punk::timeinterval::difference result audit fail" "error: s2 is $s2 but s2_test is '$s2_test' a difference of ${s2_diff} from: '$s1_test'."
}
}
proc interval_ymdhs_w_units { t1 t2 } {
# interval_ymdhs_w_units
# returns interval_ymdhs values with units
set v_list [interval_ymdhs $t2 $t1]
set i 0
set a ""
foreach f {years months days hours minutes seconds} {
append a "[lindex $v_list $i] $f \n"
incr i
}
return $a
}
}
tcl::namespace::eval punk::timeinterval::experimental {
#The interval_remains.. functions were part of the original code from the wiki
#Updated to use clock add etc - but the result seems to be off by one for the value of days - review
#The original purpose of these functions isn't clearly understood - perhaps it was just a different
#mechanism to calculate the interval as a crosscheck?
proc interval_remains_ymdhs { s1 s2 } {
@ -590,6 +580,7 @@ namespace eval punk::timeinterval {
}
proc interval_remains_ymdhs_w_units { t1 t2 } {
# interval_remains_ymdhs_w_units
# returns interval_remains_ymdhs values with units
@ -608,8 +599,6 @@ namespace eval punk::timeinterval {
# == === === === === === === === === === === === === === ===
# Sample 'about' function with punk::args documentation
# == === === === === === === === === === === === === === ===

7
src/modules/winlibreoffice-999999.0a1.0.tm

@ -217,7 +217,8 @@ namespace eval winlibreoffice {
@id -id ::winlibreoffice::to_libre_date
@cmd -name winlibreoffice::to_libre_date -help\
"Return an internal Libre Office date/time floating point
number representing the number of days since 1899-12-30.
number representing the number of days between 1899-12-30
and the supplied time.
e.g
% to_libre_date 2025-02-28T060000
@ -252,8 +253,8 @@ namespace eval winlibreoffice {
variable datebase
set tbase [clock scan $datebase -timezone $tz]
package require punk::timeinterval
set info [punk::timeinterval::interval_ymdhs -maxunit days -timezone $tz $tbase $ts]
lassign $info Y m days h m s
set info [punk::timeinterval::difference -maxunit days -timezone $tz $tbase $ts]
lassign [dict values $info] _Y _m days h m s
return [expr {$days + ((($h *3600) + ($m * 60) + $s)/86400.0)}]
}

Loading…
Cancel
Save