ClockDemo

if 0 {

Introduction

General Notes

MiHa 2015-03-03 - A demo for all the format groups recognized by the clock scan and clock format commands.

One reason for writing this program is the unwieldy manpage,
where the part about the formatting codes is hard to read,
because related formatting codes are not grouped together.

References to programs and pages here :

Designers notes

  • The list of clock-formatting-codes is somewhat unwieldy, because there are several variants scattered all about.
  • This demo lists the codes as several groups, such as date-related and time-related.
  • I use an array with each entries consists of a formatting-code as key,
    and a string with its description.
  • This description starts with a 2-character type, such as "Th" for Time-Hour,
    followed by the actual text of the description.
  • The program uses this array to produce a list, where each line shows
    a code, the result of using this code, and the description.
  • The type is used to filter/group the output.

Notes about working with tcl

  • As I already ranted, the Doku/Help has not enough useful examples.
    So, this demo is how such an example-program could look like,
    with almost everything copied/pasted directly from Tcl/Tk Documentation > TclCmd > clock .

Program


}

 # ClockDemo06.tcl - Mike Hase - 2015-03-03 / 2015-03-13
 # https://wiki.tcl-lang.org/41210

 #package require Tk

  set Prog(title)   "ClockDemo"
  set Prog(version) "v0.06"
  set Prog(date)    "2015-03-13"


 ### clock format-codes:

  # Code Type: Description
  array set fTab {        
    %a  "Wd: Day of the week,   abbreviation, localized"
    %A  "Wd: Day of the week,   full name,    localized"

    %b  "Dm: Name of the month, abbreviation, localized"
    %B  "Dm: Name of the month, full name,    localized"

    %c  "T_: Date and time of day, localized"

    %C  "Dy: Century, Indo-Arabic numerals"

    %d  "Dd: Number of the day of the month, two decimal digits"
    %D  "D_: Date, as in %m/%d/%Y"

    %e  "Dd: Number of the day of the month, one (with a leading blank) or two decimal digits"

    %g  "Dy: Two-digit year number, for use with the week-based ISO8601 calendar"
    %G  "Dy: Four-digit year number for use with the week-based ISO8601 calendar"

    %h  "Dm: Name of the month, as in %b"

    %H  "Th: Hour of the day (00-23), on a 24-hour clock."
    %I  "Th: Hour of the day (12-11), on a 12-hour clock."

    %j  "D_: Day of the year (001-366), three-digits"
    %J  "D_: Julian Day Number, since 1 January, 4713 BCE."

    %k  "Th: Hour of the day (00-23), one- or two-digits, 24-hour clock."
    %l  "Th: Hour of the day (12-11), one- or two-digits, 12-hour clock."

    %m  "Dm: Number of the month (01-12) with two digits"
    %M  "Tm: Number of the minute of the hour (00-59) with two digits."

    %N  "Dm: Number of the month (1-12) one (with a leading blank) or two digits"
    %p  "X_: Part of the day, AM or PM, localized"
    %P  "X_: Part of the day, am or pm, localized"

    %Q  "X_: (internal use:)"

    %r  "T_: Time of the day, on a 12-hour clock, localized"
    %R  "T_: Time of the day, on a 24-hour clock, localized"

    %s  "T_: Clockseconds as decimal integer"
    %S  "Ts: Second of the minute (00-59)."

    %T  "T_: Time, as in %H:%M:%S."

    %u  "Wd: Number of the day of the week (1=Monday, 7=Sunday)"
    %U  "Dw: Ordinal number of the week of the year (00-53). (obsolete)"

    %V  "Dw: Number of the ISO8601 week as a two digit number (01-53)."
    %w  "Wd: Day of the week, ordinal number  (Sunday=0; Saturday=6)."
    %W  "Dw: Week number (00-53) within the year"

    %x  "D_: Date, localized"
    %X  "T_: Time, localized"

    %y  "Dy: Year, two digits  (1938-2037)"
    %Y  "Dy: Year, four digits (1938-2037)"

    %z  "X_: Timezone, in hours and minutes east (+hhmm) or west (-hhmm) of Greenwich."
    %Z  "X_: Timezone as name, localized"

    %+  "T_: TimeDate, as in %a %b %e %H:%M:%S %Z %Y"
  }


 ### Display:

  proc showTD {} {
    global cs td  
    set td [clock format $cs  -format "%Y-%m-%d  %H:%M:%S" ]
    puts "--"
    puts "clock seconds: $cs          TimeDate: $td"
  }

  proc show0 {} {
    global cs td  fTab

    puts "\nAll codes, unsorted:"
    foreach {fc descr} [array get fTab] {
      set res [clock format $cs  -format $fc ]
      puts [format "%-3s %-28s  %s" $fc $res $descr]
    }
  }

  proc show1 { select title } {
    global cs td  fTab

    puts "\n$title:"

    set res "xx"
    set i 0
    foreach fc [lsort -dict [array names fTab] ] {
      incr i 1
      set descr $fTab($fc)
      set type  [string range $descr 0 0]
      set desc1 [string range $descr 4 end]
      if {$type == $select} {
        set res [clock format $cs  -format $fc ]
        puts [format "%-3s %-28s  %s" $fc $res $desc1]
      }
    }
  }

  proc show2 { select title } {
    global cs td  fTab

    puts "\n$title:"

    set res "xx"
    set i 0
    foreach fc [lsort -dict [array names fTab] ] {
      incr i 1
      set descr $fTab($fc)
      set type  [string range $descr 0 1]
      set desc1 [string range $descr 4 end]
      if {$type == $select} {
        set res [clock format $cs  -format $fc ]
        puts [format "%-3s %-28s  %s" $fc $res $desc1]
      }
    }
  }

  proc show3 {} {
    show1 "D"  "Formatting codes for date"
    show1 "T"  "Formatting codes for time"
    show1 "W"  "Formatting codes for weekdays"
    show1 "X"  "Other formatting codes"
  }

  proc show4 {} {
    show2 "D_" "Formatting codes for date - combinations"
    show2 "Dd" "Formatting codes for date - Day"
    show2 "Dm" "Formatting codes for date - Month"
    show2 "Dy" "Formatting codes for date - Year"

    show2 "T_" "Formatting codes for time - combinations"
    show2 "Th" "Formatting codes for time - Hour"
    show2 "Tm" "Formatting codes for time - Minute"
    show2 "Ts" "Formatting codes for time - Second"

    show1 "W"  "Formatting codes for weekdays"
    show1 "X"  "Other formatting codes"
  }


 ### Time:

  proc now {} {
    global cs td  fTab

    set cs [clock seconds]
    set td [clock format $cs  -format "%Y-%m-%d  %H:%M:%S" ]
  }


 ### Time/Repeat/Wait:

  proc every {ms body} {
    if 1 $body
    after $ms [list after idle [namespace code [info level 0]]]
  }
  proc run  {} {every 10000 {now; showTD} }
  proc stop {} {foreach id [after info] {after cancel $id}; }


 ### Test+Debug:

  proc ?    {} { help }
  proc help {} {
    puts "--"
    puts "argv0 : $::argv0"
    puts "argv  : $::argv"
    puts "tcl/tk: $::tcl_patchLevel / $::tk_patchLevel"
    puts "now,t1:change time, x,y,z, showTD,show3,show4,  e:exit"
  }

  proc t1 {} { set ::cs [clock scan {1987-12-31 13:14:15} -format {%Y-%m-%d %H:%M:%S}] }
  proc x  {} { showTD; show0 }
  proc y  {} { showTD; show3 }
  proc z  {} { showTD; show4 }

  proc e  {} { exit }



 ### Main:

   wm title . "$Prog(title) $Prog(version)"
   puts       "$Prog(title) $Prog(version)"

   bind .  <F2>     { console show }
   catch {console show}        ;##
   catch {wm withdraw .}

   t1
  #now
   showTD
  #show0

   show3
  #show4

   help

 ### EOF ###

Output

ClockDemo v0.06
--
clock seconds: 567951255          TimeDate: 1987-12-31  13:14:15

Formatting codes for date:
%B  December                      Name of the month, full name,    localized
%b  Dec                           Name of the month, abbreviation, localized
%C  19                            Century, Indo-Arabic numerals
%D  12/31/1987                    Date, as in %m/%d/%Y
%d  31                            Number of the day of the month, two decimal digits
%e  31                            Number of the day of the month, one (with a leading blank) or two decimal digits
%G  1987                          Four-digit year number for use with the week-based ISO8601 calendar
%g  87                            Two-digit year number, for use with the week-based ISO8601 calendar
%h  Dec                           Name of the month, as in %b
%J  2447161                       Julian Day Number, since 1 January, 4713 BCE.
%j  365                           Day of the year (001-366), three-digits
%m  12                            Number of the month (01-12) with two digits
%N  12                            Number of the month (1-12) one (with a leading blank) or two digits
%U  52                            Ordinal number of the week of the year (00-53). (obsolete)
%V  53                            Number of the ISO8601 week as a two digit number (01-53).
%W  52                            Week number (00-53) within the year
%x  12/31/1987                    Date, localized
%Y  1987                          Year, four digits (1938-2037)
%y  87                            Year, two digits  (1938-2037)

Formatting codes for time:
%+  Thu Dec 31 13:14:15 CET 1987  TimeDate, as in %a %b %e %H:%M:%S %Z %Y
%c  Thu Dec 31 13:14:15 1987      Date and time of day, localized
%H  13                            Hour of the day (00-23), on a 24-hour clock.
%I  01                            Hour of the day (12-11), on a 12-hour clock.
%k  13                            Hour of the day (00-23), one- or two-digits, 24-hour clock.
%l   1                            Hour of the day (12-11), one- or two-digits, 12-hour clock.
%M  14                            Number of the minute of the hour (00-59) with two digits.
%R  13:14                         Time of the day, on a 24-hour clock, localized
%r  01:14:15 pm                   Time of the day, on a 12-hour clock, localized
%S  15                            Second of the minute (00-59).
%s  567951255                     Clockseconds as decimal integer
%T  13:14:15                      Time, as in %H:%M:%S.
%X  13:14:15                      Time, localized

Formatting codes for weekdays:
%A  Thursday                      Day of the week,   full name,    localized
%a  Thu                           Day of the week,   abbreviation, localized
%u  4                             Number of the day of the week (1=Monday, 7=Sunday)
%w  4                             Day of the week, ordinal number  (Sunday=0; Saturday=6).

Other formatting codes:
%P  pm                            Part of the day, am or pm, localized
%p  PM                            Part of the day, AM or PM, localized
%Q  Stardate 41997.5              (internal use:)
%Z  CET                           Timezone as name, localized
%z  +0100                         Timezone, in hours and minutes east (+hhmm) or west (-hhmm) of Greenwich.
--

Remarks

if 0 {

MiHa 2015-03-03 - It looks like there is no formatting code for the total minutes of the day (0-1440).
Same for seconds (0-86400).


RS 2015-03-16 - This returns the seconds since midnight for a given timestamp (divide by 60 for minutes :^):

 proc sec_since_midnight time {
   set midnight [clock format $time -format %Y-%m-%d]
   set diff [expr {$time - [clock scan $midnight -gmt 1]}]
 }

Testing:

 % sec_since_midnight [clock scan now]
 36334
 % clock format [sec_since_midnight [clock scan now]]
 Thu Jan 01 11:05:36 CET 1970

Some questions:

MiHa 2015-03-13 - Now the output can be listed with more category-groups (show3, show4).

ToDo:

  • include the more exotic codes, like %EC, %Od, %Oe, %OH, etc.
  • combine show1, show2

RLE (2015-05-16): Strings into table cells? Depends upon what you want to accomplish. For simple GUI use, label elements with proper -anchor, -justify and -wraplength will provide "cell wrapping" and grid can then be used to arrange the labels into a table visually. But if you are looking for tabular output of random data (i.e., database query table output display) then this method is not the right choice.

For word wrapping to some width, look into the textutil::adjust routines in tcllib.

Converting the string values for hours or minutes into integers is best done with scan. It does not interpret leading zero values as octal, so you don't get the problem with 08 and 09 giving the 'invalid octal number' error.

You can even use scan to extract all three in one go:

  % clock format [clock seconds] -format %H:%M:%S
  13:25:45
  % scan [clock format [clock seconds] -format %H:%M:%S] "%d:%d:%d" h m s
  3
  % puts "$h  $m  $s"
  13  26  6
  % incr h ; incr m ; incr s
  7
  % puts "$h  $m  $s"
  14  27  7

MiHa: In the program above, for example the entry for "%e" is quite long, and wrapping in the tcl-console doesn't look nice.
Therefore, I was looking for a simple way to format such strings, without GUI/Tk or html.

RLE (2015-05-18): In that case. simple word wrap without GUI/Tk or html, look into the textutil::adjust routine in tcllib that I referred you to above.

}