From 72648be984af7dc3a1008c8c9274f175f81d5a90 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Mon, 17 Mar 2025 01:09:48 +1100 Subject: [PATCH] tidy up API for punk::timeinterval, adjust winlibreoffice to match --- src/modules/punk/timeinterval-999999.0a1.0.tm | 119 ++++++++---------- src/modules/winlibreoffice-999999.0a1.0.tm | 7 +- 2 files changed, 58 insertions(+), 68 deletions(-) diff --git a/src/modules/punk/timeinterval-999999.0a1.0.tm b/src/modules/punk/timeinterval-999999.0a1.0.tm index cb021427..6acdc8b9 100644 --- a/src/modules/punk/timeinterval-999999.0a1.0.tm +++ b/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 # == === === === === === === === === === === === === === === diff --git a/src/modules/winlibreoffice-999999.0a1.0.tm b/src/modules/winlibreoffice-999999.0a1.0.tm index 57954a0b..5a9b52d3 100644 --- a/src/modules/winlibreoffice-999999.0a1.0.tm +++ b/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)}] }