clock(n)

πŸ•°οΈ clock(n) β€” the Tcl Built-In Commands era πŸ’–

okay bestie so this is clock(n), one of Tcl's built-in commands, and she is booked and busy ✨


✨ NAME ✨

clock β€” obtain and manipulate dates and times πŸŽ€


🌸 SYNOPSIS 🌸

package require Tcl 8.5-

clock add timeVal ?count unit...? ?-option value?
clock clicks ?-option?
clock format timeVal ?-option value...?
clock microseconds
clock milliseconds
clock scan inputString ?-option value...?
clock seconds

πŸ’… DESCRIPTION πŸ’…

so clock does a whole bunch of operations β€” it obtains values that represent times and it manipulates them too. she supports several subcommands that decide which action actually gets carried out. icon behaviour, honestly πŸ‘‘

  • clock add timeVal ?count unit...? ?-option value? β€” adds a (possibly negative, we love a negative queen) offset to a time that's expressed as an integer number of seconds. full deets live in CLOCK ARITHMETIC.
  • clock clicks ?-option? β€” if you don't hand her a -option argument, she returns a high-resolution time value as a system-dependent integer value. the unit of that value is system-dependent too, but it should be the highest resolution clock available on the system, like a CPU cycle counter. see HIGH RESOLUTION TIMERS for the full rundown.

if the -option argument is -milliseconds, then the command is synonymous with clock milliseconds (peep below). this usage is obsolete though β€” clock milliseconds is to be considered the preferred way of obtaining a count of milliseconds.

if the -option argument is -microseconds, then the command is synonymous with clock microseconds (also peep below). this usage is obsolete too β€” clock microseconds is to be considered the preferred way of obtaining a count of microseconds.

  • clock format timeVal ?-option value...? β€” formats a time expressed as an integer number of seconds into a format that's intended for consumption by users or external programs. see FORMATTING TIMES for the full description.
  • clock microseconds β€” returns the current time as an integer number of microseconds. see HIGH RESOLUTION TIMERS for the full description.
  • clock milliseconds β€” returns the current time as an integer number of milliseconds. see HIGH RESOLUTION TIMERS for the full description.
  • clock scan inputString ?-option value...? β€” scans a time that's expressed as a character string and produces an integer number of seconds. see SCANNING TIMES for the full description.
  • clock seconds β€” returns the current time as an integer number of seconds. simple. elegant. slay.

πŸ¦‹ PARAMETERS πŸ¦‹

  • count β€” an integer representing a count of some unit of time. see CLOCK ARITHMETIC for the details, bestie.
  • timeVal β€” an integer value you pass to the clock command that represents an absolute time as a number of seconds from the epoch time of 1 January 1970, 00:00 UTC. heads up though: that count of seconds does not include any leap seconds. seconds are counted as if every single UTC day has exactly 86400 seconds. Tcl deals with leap seconds by speeding up or slowing down its clock by a tiny fraction for some minutes until it's back in sync with UTC β€” its data model does not represent minutes that have 59 or 61 seconds. no cap 🫢
  • now β€” instead of timeVal you can use a non-integer value, now, as a replacement for today. it's simply interpolated at run-time as the value of clock seconds. for example:
clock format now -f %a; # current day of the week

clock add now 1 month; # next month
  • unit β€” one of the words seconds, minutes, hours, days, weekdays, weeks, months, or years. used together with count to identify an interval of time, like 3 seconds or 1 year. yes ma'am πŸŽ€

πŸ‘‘ OPTIONS πŸ‘‘

  • -base time β€” says that any relative times present in a clock scan command are to be given relative to time. time must be expressed as a count of nominal seconds from the epoch time of 1 January 1970, 00:00 UTC.
  • -format format β€” specifies the desired output format for clock format, or the expected input format for clock scan. the format string consists of any number of characters other than the per-cent sign (β€œ%”) interspersed with any number of format groups, which are two- or three-character sequences beginning with the per-cent sign. the permissible format groups, and their interpretation, are described under FORMAT GROUPS.

on clock format, the default format is

%a %b %d %H:%M:%S %Z %Y

on clock scan, the lack of a -format option indicates that a β€œfree format scan” is requested β€” see FREE FORM SCAN for a description of what happens. she's freestyling πŸ’ƒ

  • -gmt boolean β€” if boolean is true, specifies that a time specified to clock add, clock format or clock scan should be processed in UTC. if boolean is false, the processing defaults to the local time zone. this usage is obsolete; the correct current usage is to specify the UTC time zone with -timezone :UTC or any of the equivalent ways to specify it.
  • -locale localeName β€” specifies that locale-dependent scanning and formatting (and date arithmetic for dates preceding the adoption of the Gregorian calendar) is to be done in the locale identified by localeName. the locale name may be any of the locales acceptable to the msgcat package, or it may be the special name system, which represents the current locale of the process, or the null string, which represents Tcl's default locale.

the effect of locale on scanning and formatting is discussed in the descriptions of the individual format groups under FORMAT GROUPS. the effect of locale on clock arithmetic is discussed under CLOCK ARITHMETIC.

  • -timezone zoneName β€” specifies that clock arithmetic, formatting, and scanning are to be done according to the rules for the time zone specified by zoneName. the permissible values, and their interpretation, are discussed under TIME ZONES. on subcommands that expect a -timezone argument, the default is to use the current time zone. the current time zone is determined, in order of preference, by:
    1. the environment variable TCL_TZ.
    2. the environment variable TZ.
    3. on Windows systems, the time zone settings from the Control Panel.
  • -validate boolean β€” if boolean is true (that's the default, btw), clock scan will raise an error if the input contains invalid values, e.g. day of month greater than number of days in the month. if specified as false, the command makes an adjustment to bring values within acceptable range. see SCANNING TIMES for details.
ngl if none of these is present, the C localtime and mktime functions are used to attempt to convert times between local and Greenwich. and on 32-bit systems, this approach is likely to have bugs 😭 β€” particularly for times that lie outside the window (approximately the years 1902 to 2037) that can be represented in a 32-bit integer. she's doing her best but that window is small.

✨ CLOCK ARITHMETIC ✨

Okay bestie, so clock add is literally out here doing math on time. It takes a value (that's your nominal seconds from the epoch time of 1 January 1970, 00:00 UTC) as its first argument. Then all the rest of the arguments β€” well, except for the possible -timezone, -locale and -gmt options β€” are integers and keywords, alternating back and forth. And those keywords? They gotta be one of seconds, minutes, hours, days, weekdays, weeks, months, or years. No substitutions, periodt.

Adding seconds, minutes and hours is pretty chill actually. The time increment you give it just gets added straight to the timeVal you handed to clock add β€” and yeah, minutes get multiplied by sixty and hours get multiplied by 3600. Then the result is read as a nominal number of seconds from the Epoch. Easy.

Now, the tea: surprising results may be obtained when crossing a point at which a leap second is inserted or removed. Because clock add just straight up ignores leap seconds and assumes times come in sequence like 23:59:58, 23:59:59, 00:00:00. And how does that work out? Well, Tcl's model of time reacts to leap seconds by speeding or slowing the clock by a miniscule amount until Tcl's time is back in step with the world. She's just adjusting her vibe, okay? πŸ¦‹

The fact that adding and subtracting hours is defined in terms of absolute time means it will add fixed amounts of time in time zones that observe summer time (Daylight Saving Time). So like, this code right here sets x to 04:00:00 because the clock has changed in the interval in question:

set s [clock scan {2004-10-30 05:00:00} \
           -format {%Y-%m-%d %H:%M:%S} \
           -timezone :America/New_York]
set a [clock add $s 24 hours -timezone :America/New_York]
set x [clock format $a \
           -format {%H:%M:%S} -timezone :America/New_York]

Adding and subtracting days and weeks? Different energy entirely. That's done by converting the given time to a calendar day and time of day in the appropriate time zone and locale. The requisite number of days gets added to the calendar day (and yes, weeks are converted to days by multiplying by seven), and then the date and time get converted back into a count of seconds from the epoch time. The weekdays keyword is basically days with one lil glow-up: weekends β€” Saturdays and Sundays β€” are skipped. πŸ’…

So if you add or subtract a given number of days across the point that the time changes at the start or end of summer time (Daylight Saving Time), you end up with the same local time on the day in question. For instance, this sets x to 05:00:00:

set s [clock scan {2004-10-30 05:00:00} \
           -format {%Y-%m-%d %H:%M:%S} \
           -timezone :America/New_York]
set a [clock add $s 1 day -timezone :America/New_York]
set x [clock format $a \
           -format {%H:%M:%S} -timezone :America/New_York]

When it gets ambiguous β€” like the same local time happens twice on the same day β€” the earlier time is used. Simple as that. And when the conversion yields an impossible time (say, 02:30 during the Spring Daylight Saving Time change using US rules), the time is converted as if the clock had not changed. So this next one sets x to 03:30:00:

set s [clock scan {2004-04-03 02:30:00} \
           -format {%Y-%m-%d %H:%M:%S} \
           -timezone :America/New_York]
set a [clock add $s 1 day -timezone :America/New_York]
set x [clock format $a \
           -format {%H:%M:%S} -timezone :America/New_York]

Adding a given number of days or weeks works correctly across the conversion between the Julian and Gregorian calendars β€” the omitted days are just skipped, iconic behaviour honestly. This code sets z to 1752-09-14:

set x [clock scan 1752-09-02 -format %Y-%m-%d -locale en_US]
set y [clock add $x 1 day -locale en_US]
set z [clock format $y -format %Y-%m-%d -locale en_US]

And in the truly bizarre case where adding the given number of days yields a date that does not exist because it falls within the dropped days of the Julian-to-Gregorian conversion, the date is converted as if it was on the Julian calendar. Weird but she said what she said. πŸ™ˆ

Adding a number of months, or a number of years, is similar β€” it converts the given time to a calendar date and time of day, adds the requisite number of months or years, and then reconverts the resulting date and time of day to an absolute time.

If the resulting date is impossible because the month has too few days (classic example: adding 1 month to 31 January), the last day of the month is substituted. So adding 1 month to 31 January gives you 28 February in a common year, or 29 February in a leap year. Slay, February.

The rules for handling anomalies relating to summer time and to the Gregorian calendar are the exact same when you're adding/subtracting months and years as they are when you're adding/subtracting days and weeks. Consistency queen. πŸ‘‘

Oh and if multiple count unit pairs are present on the command, they are evaluated consecutively, from left to right. No skipping around.


⏱️ HIGH RESOLUTION TIMERS ⏱️

Most of the subcommands supported by the clock command deal with times represented as a count of seconds from the epoch time, and that's the representation clock seconds returns. But there are three exceptions, and they all exist for when you need higher-resolution times.

  • clock milliseconds returns the count of milliseconds from the epoch time.
  • clock microseconds returns the count of microseconds from the epoch time.
  • clock clicks returns a platform-dependent high-resolution timer.

And heads up, bestie: unlike clock seconds and clock milliseconds, the value of clock clicks is not guaranteed to be tied to any fixed epoch. It's simply intended to be the most precise interval timer available, and it's intended only for relative timing studies such as benchmarks. So don't go trying to read a date out of it, okay? 😭


πŸŽ€ FORMATTING TIMES πŸŽ€

The clock format command produces times for display to a user or writing to an external medium. It accepts times that are expressed in seconds from the epoch time of 1 January 1970, 00:00 UTC, as returned by clock seconds, clock scan, clock add, file atime or file mtime.

If a -format option is present, the following argument is a string that specifies how the date and time are to be formatted. That string consists of any number of characters other than the per-cent sign (%), interspersed with any number of format groups β€” and format groups are two-character sequences beginning with the per-cent sign. The permissible format groups, and their interpretation, are described under FORMAT GROUPS.

If a -timezone option is present, the following argument is a string that specifies the time zone in which the date and time are to be formatted. And as an alternative to -timezone :UTC, the obsolete usage -gmt true may be used. See TIME ZONES for the permissible variants for the time zone.

If a -locale option is present, the following argument is a string that specifies the locale in which the time is to be formatted, in the same format that is used for the msgcat package. Quick heads up though β€” the default, if -locale is not specified, is the root locale {} rather than the current locale. If you want the current locale, use -locale current. ✨

Also, some platforms support a system locale that reflects the user's current choices. Like on Windows, the format the user has selected from dates and times in the Control Panel can be obtained by using the system locale. And on platforms that do not define a user selection of date and time formats separate from LC_TIME, -locale system is synonymous with -locale current.

πŸ’– SCANNING TIMES πŸ’–

okay so bestie, clock scan is the vibe where you hand it a time as a string and it gives you back the number of seconds since the epoch time of 1 January 1970, 00:00 UTC. iconic. It normally takes a -format option followed by a string that describes the expected format of the input. (If you wanna know what clock scan does without that argument, go read FREE FORM SCAN.) The format string is any number of characters that aren't the percent sign %, with any number of format groups mixed in. A format group is a two-character sequence that starts with %. The allowed format groups and how they're interpreted are listed under FORMAT GROUPS. πŸ’…

If a -timezone option is present, the next argument is a string that says which time zone the date and time are interpreted in. Instead of -timezone :UTC, you can use the obsolete usage -gmt true. For all the permissible time zone variants, check TIME ZONES. πŸ•°οΈ

If a -locale option is present, the next argument is a string that specifies the locale in which the time is interpreted, in the same format used for the msgcat package. Important: if -locale is not specified, the default is the root locale {} rather than the current locale. You can get the current locale with -locale current. Also, some platforms support a system locale that reflects the user's current choices. For example, on Windows, the format the user picked from dates and times in the Control Panel can be obtained by using the system locale. On platforms that don't define a user selection of date and time formats separate from LC_TIME, -locale system is synonymous with -locale current. 🌍

If a -base option is present, the next argument is a time (expressed in seconds from the epoch time) used as the base time for interpreting relative times. If no -base option is present, the base time is the current time. ⏳

Scanning times in fixed format works by figuring out three things: the date, the time of day, and the time zone. Then those three get combined into a point in time, returned as the number of seconds from the epoch. 🎯

Before scanning starts, the format string is preprocessed to replace %c, %Ec, %x, %Ex, %X. %Ex, %r, %R, %T, %D, %EY and %+ format groups with counterparts that are appropriate to the current locale and contain none of the above groups. For instance, %D will (in the en_US locale) be replaced with %m/%d/%Y. ✨

The date is determined according to the fields that are present in the preprocessed format string. In order of preference:

  1. If the string contains a %s format group, representing seconds from the epoch, that group is used to determine the date.
  2. If the string contains a %J, %EJ or %Ej format groups, representing the Calendar or Astronomical Julian Day Number, those groups are used to determine the date. Note that in the case of %EJ or %Ej format groups, representing the Julian Date with time fraction, these groups may be used to determine the date and time.
  3. If the string contains a complete set of format groups specifying century, year, month, and day of month; century, year, and day of year; or ISO8601 fiscal year, week of year, and day of week; those groups are combined and used to determine the date. If more than one complete set is present, the one at the rightmost position in the string is used.
  4. If the string lacks a century but contains a set of format groups specifying year of century, month and day of month; year of century and day of year; or two-digit ISO8601 fiscal year, week of year, and day of week; those groups are combined and used to determine the date. If more than one complete set is present, the one at the rightmost position in the string is used. The year is presumed to lie in the range 1938 to 2037 inclusive.
  5. If the string entirely lacks any specification for the year (or contains the year only on the locale's alternative calendar) and contains a set of format groups specifying month and day of month, day of year, or week of year and day of week, those groups are combined and used to determine the date. If more than one complete set is present, the one at the rightmost position in the string is used. The year is determined by interpreting the base time in the given time zone.
  6. If the string contains none of the above sets, but has a day of the month or day of the week, the day of the month or day of the week are used to determine the date by interpreting the base time in the given time zone and returning the given day of the current week or month. (The week runs from Monday to Sunday, ISO8601-fashion.) If both day of month and day of week are present, the day of the month takes priority.
  7. If none of the above rules results in a usable date, the date of the base time in the given time zone is used.

The time is also determined according to the fields that are present in the preprocessed format string. In order of preference:

  1. If the string contains a %s format group, representing seconds from the epoch, that group determines the time of day.
  2. If the string contains either an hour on the 24-hour clock or an hour on the 12-hour clock plus an AM/PM indicator, that hour determines the hour of the day. If the string further contains a group specifying the minute of the hour, that group combines with the hour. If the string further contains a group specifying the second of the minute, that group combines with the hour and minute.
  3. If the string contains neither a %s format group nor a group specifying the hour of the day, then midnight (00:00, the start of the given date) is used. The time zone is determined by either the -timezone or -gmt options, or by using the current time zone.

If a format string lacks a %z or %Z format group, it's possible for the time to be ambiguous because it appears twice in the same day, once without and once with Daylight Saving Time. If this situation occurs, the first occurrence of the time is chosen. (For this reason, it's wise to have the input string contain the time zone when converting local times. This caveat does not apply to UTC times.) 😭

If the interpretation of the groups yields an impossible time because a field is out of range, an exception is raised if the -validate option is not present or passed as true. If passed as false, enough of that field's unit will be added to or subtracted from the time to bring it in range. Thus, if attempting to scan or format day 0 of the month, one day will be subtracted from day 1 of the month, yielding the last day of the previous month. πŸ’€

If the interpretation of the groups yields an impossible time because a Daylight Saving Time change skips over that time, or an ambiguous time because a Daylight Saving Time change skips back so that the clock observes the given time twice, and no time zone specifier (%z or %Z) is present in the format, the time is interpreted as if the clock had not changed. πŸŒ€


🌈 FORMAT GROUPS 🌈

The following format groups are recognized by the clock scan and clock format commands. πŸ‘‘

  • %a β€” On output, produces an abbreviation (e.g., Mon) for the day of the week in the given locale. On input, matches the name of the day of the week in the given locale (in either abbreviated or full form, or any unique prefix of either form).
  • %A β€” On output, produces the full name (e.g., Monday) of the day of the week in the given locale. On input, matches the name of the day of the week in the given locale (in either abbreviated or full form, or any unique prefix of either form).
  • %b β€” On output, produces an abbreviation (e.g., Jan) for the name of the month in the given locale. On input, matches the name of the month in the given locale (in either abbreviated or full form, or any unique prefix of either form).
  • %B β€” On output, produces the full name (e.g., January) of the month in the given locale. On input, matches the name of the month in the given locale (in either abbreviated or full form, or any unique prefix of either form).
  • %c β€” On output, produces a localized representation of date and time of day; the localized representation is expected to use the Gregorian calendar. On input, matches whatever %c produces.
  • %C β€” On output, produces the number of the century in Indo-Arabic numerals. On input, matches one or two digits, possibly with leading whitespace, that are expected to be the number of the century.
  • %d β€” On output, produces the number of the day of the month, as two decimal digits. On input, matches one or two digits, possibly with leading whitespace, that are expected to be the number of the day of the month.
  • %D β€” This format group is synonymous with %m/%d/%Y. It should be used only in exchanging data within the en_US locale, since other locales typically do not use this order for the fields of the date.
  • %e β€” On output, produces the number of the day of the month, as one or two decimal digits (with a leading blank for one-digit dates). On input, matches one or two digits, possibly with leading whitespace, that are expected to be the number of the day of the month.
  • %Ec β€” On output, produces a locale-dependent representation of the date and time of day in the locale's alternative calendar. On input, matches whatever %Ec produces. The locale's alternative calendar need not be the Gregorian calendar.
  • %EC β€” On output, produces a locale-dependent name of an era in the locale's alternative calendar. On input, matches the name of the era or any unique prefix.
  • %EE β€” On output, produces the string B.C.E. or C.E., or a string of the same meaning in the locale, to indicate whether %Y refers to years before or after Year 1 of the Common Era. On input, accepts the string B.C.E., B.C., C.E., A.D., or the abbreviation appropriate to the current locale, and uses it to fix whether %Y refers to years before or after Year 1 of the Common Era.
  • %Ej β€” output-wise, bestie, this hands you a string of digits with the Astronomical Julian Date or Astronomical Julian Day Number (JDN/JD) πŸͺ. And here's the twist: unlike calendar julian day %J, it starts the day at noon, not midnight. Iconic but chaotic. On input, it takes a string of digits (or a floating point with the time fraction, fancy) and reads it as an Astronomical Julian Day Number (JDN/JD). So what even is the Astronomical Julian Date? It's a count of the number of calendar days that have elapsed since 1 January, 4713 BCE of the proleptic Julian calendar, and yes it contains the time fraction too (after the floating point). The epoch time of 1 January 1970 corresponds to Astronomical JDN 2440587.5. This value corresponds the julian day used in sqlite-database, and is the same as result of select julianday(:seconds, 'unixepoch'). Slay.
  • %EJ β€” on output this produces a string of digits giving the Calendar Julian Date. And it's giving opposite energy to the julian day %J format group, because it produces a float number. And opposite to the astronomical julian day %Ej group, it starts at midnight. On input, accepts a string of digits (or floating point with the time fraction) and interprets it as a Calendar Julian Day Number. The Calendar Julian Date is a count of the number of calendar days that have elapsed since 1 January, 4713 BCE of the proleptic Julian calendar, which also contains the time fraction (after floating point). The epoch time of 1 January 1970 corresponds to Astronomical JDN 2440588. πŸŒ™
  • %Es β€” this one affects similar to %s, but in opposition to %s it parses or formats local seconds (not the posix seconds, okay periodt). And because %s has the same precedence as %s (it uniquely determines a point in time), it overrides all other input formats. It said what it said πŸ’…
  • %Ex β€” on output, produces a locale-dependent representation of the date in the locale's alternative calendar. On input, matches whatever %Ex produces. And heads up bestie: the locale's alternative calendar need not be the Gregorian calendar. Wild, I know.
  • %EX β€” on output, produces a locale-dependent representation of the time of day in the locale's alternative numerals. On input, matches whatever %EX produces. πŸ•
  • %Ey β€” on output, produces a locale-dependent number of the year of the era in the locale's alternative calendar and numerals. On input, matches such a number.
  • %EY β€” on output, produces a representation of the year in the locale's alternative calendar and numerals. On input, matches what %EY produces. Often synonymous with %EC%Ey. ✨
  • %g β€” on output, produces a two-digit year number suitable for use with the week-based ISO8601 calendar; that is, the year number corresponds to the week number produced by %V. On input, accepts such a two-digit year number, possibly with leading whitespace. πŸ—“οΈ
  • %G β€” on output, produces a four-digit year number suitable for use with the week-based ISO8601 calendar; that is, the year number corresponds to the week number produced by %V. On input, accepts such a four-digit year number, possibly with leading whitespace.
  • %h β€” this format group is synonymous with %b. That's it, that's the whole thing 🫢
  • %H β€” on output, produces a two-digit number giving the hour of the day (00-23) on a 24-hour clock. On input, accepts such a number.
  • %I β€” on output, produces a two-digit number giving the hour of the day (12-11) on a 12-hour clock. On input, accepts such a number.
  • %j β€” on output, produces a three-digit number giving the day of the year (001-366). On input, accepts such a number.
  • %J β€” on output, produces a string of digits giving the Julian Day Number. On input, accepts a string of digits and interprets it as a Julian Day Number. The Julian Day Number is a count of the number of calendar days that have elapsed since 1 January, 4713 BCE of the proleptic Julian calendar. The epoch time of 1 January 1970 corresponds to Julian Day Number 2440588. No time fraction here, she's clean ✨
  • %k β€” on output, produces a one- or two-digit number giving the hour of the day (0-23) on a 24-hour clock. On input, accepts such a number.
  • %l β€” on output, produces a one- or two-digit number giving the hour of the day (12-11) on a 12-hour clock. On input, accepts such a number.
  • %m β€” on output, produces the number of the month (01-12) with exactly two digits. On input, accepts two digits and interprets them as the number of the month.
  • %M β€” on output, produces the number of the minute of the hour (00-59) with exactly two digits. On input, accepts two digits and interprets them as the number of the minute of the hour.
  • %N β€” on output, produces the number of the month (1-12) with one or two digits, and a leading blank for one-digit dates (cute). On input, accepts one or two digits, possibly with leading whitespace, and interprets them as the number of the month.
  • %Od, %Oe, %OH, %OI, %Ok, %Ol, %Om, %OM, %OS, %Ou, %Ow, %Oy β€” all of these format groups are synonymous with their counterparts without the "O", except that the string is produced and parsed in the locale-dependent alternative numerals. So like, same vibe, different numerals πŸ‘‘
  • %p β€” on output, produces an indicator for the part of the day, AM or PM, appropriate to the given locale. If the script of the given locale supports multiple letterforms, lowercase is preferred. On input, matches the representation AM or PM in the given locale, in either case.
  • %P β€” on output, produces an indicator for the part of the day, am or pm, appropriate to the given locale. If the script of the given locale supports multiple letterforms, uppercase is preferred. On input, matches the representation AM or PM in the given locale, in either case.
  • %Q β€” this format group is reserved for internal use within the Tcl library. Not for us, bestie, it's giving backstage pass πŸŽ€
  • %r β€” on output, produces a locale-dependent time of day representation on a 12-hour clock. On input, accepts whatever %r produces.
  • %R β€” on output, the time in 24-hour notation (%H:%M). For a version including the seconds, see %T below. On input, accepts whatever %R produces.
  • %s β€” on output, simply formats the timeVal argument as a decimal integer and inserts it into the output string. On input, accepts a decimal integer and uses is as the time value without any further processing. Since %s uniquely determines a point in time, it overrides all other input formats. Main character energy fr fr πŸ’…
  • %S β€” on output, produces a two-digit number of the second of the minute (00-59). On input, accepts two digits and uses them as the second of the minute.
  • %t β€” on output, produces a TAB character. On input, matches a TAB character. That's literally it 🫢
  • %T β€” synonymous with %H:%M:%S.
  • %u β€” on output, produces the number of the day of the week (1β†’Monday, 7β†’Sunday). On input, accepts a single digit and interprets it as the day of the week. Sunday may be either 0 or 7.
  • %U β€” on output, produces the ordinal number of the week of the year (00-53). The first Sunday of the year is the first day of week 01. On input accepts two digits which are otherwise ignored. This format group is never used in determining an input date. This interpretation of the week of the year was once common in US banking but is now largely obsolete. See %V for the ISO8601 week number. πŸ’€ obsolete but we respect the elders
  • %V β€” on output, produces the number of the ISO8601 week as a two digit number (01-53). Week 01 is the week containing January 4; or the first week of the year containing at least 4 days; or the week containing the first Thursday of the year (the three statements are equivalent, yes really). Each week begins on a Monday. On input, accepts the ISO8601 week number. πŸ—“οΈβœ¨
  • %w β€” on output, produces the ordinal number of the day of the week (Sunday==0; Saturday==6). On input, accepts a single digit and interprets it as the day of the week; Sunday may be represented as either 0 or 7. Note that %w is not the ISO8601 weekday number, which is produced and accepted by %u. Don't mix them up bestie, they're cousins not twins.
  • %W β€” on output, produces a week number (00-53) within the year; week 01 begins on the first Monday of the year. On input, accepts two digits, which are otherwise ignored. This format group is never used in determining an input date. It is not the ISO8601 week number; that week is produced and accepted by %V.
  • %x β€” on output, produces the date in a locale-dependent representation. On input, accepts whatever %x produces and is used to determine calendar date.
  • %X β€” on output, produces the time of day in a locale-dependent representation. On input, accepts whatever %X produces and is used to determine time of day.
  • %y β€” on output, produces the two-digit year of the century. On input, accepts two digits, and is used to determine calendar date. The date is presumed to lie between 1938 and 2037 inclusive. Note that %y does not yield a year appropriate for use with the ISO8601 week number %V; programs should use %g for that purpose. ⚠️
  • %Y β€” on output, produces the four-digit calendar year. On input, accepts four digits and may be used to determine calendar date. Note that %Y does not yield a year appropriate for use with the ISO8601 week number %V; programs should use %G for that purpose. ⚠️
  • %z β€” on output, produces the current time zone, expressed in hours and minutes east (+hhmm) or west (-hhmm) of Greenwich. On input, accepts a time zone specifier (see TIME ZONES below) that will be used to determine the time zone (this token is optionally applicable on input, so the value is not mandatory and can be missing in input). 🌍
  • %Z β€” on output, produces the current time zone's name, possibly translated to the given locale. On input, accepts a time zone specifier (see TIME ZONES below) that will be used to determine the time zone (token is also like %z optionally applicable on input). This option should, in general, be used on input only when parsing RFC822 dates. Other uses are fraught with ambiguity; for instance, the string BST may represent British Summer Time or Brazilian Standard Time. It is recommended that date/time strings for use by computers use numeric time zones instead.
okay so real talk, that %Z ambiguity? It's giving red flag. Numeric time zones only, bestie, trust 🚩
  • %% β€” on output, produces a literal "%" character. On input, matches a literal "%" character.
  • %+ β€” synonymous with "%a %b %e %H:%M:%S %Z %Y". The whole kit and kaboodle πŸ’–

🌍 TIME ZONES

okay so when clock is out here processing a local time, it's got a whole ranked list of places it'll go looking for a time zone. In order of preference, bestie:

  1. A time zone specified inside a string being parsed and matched by a %z or %Z format group.
  2. A time zone specified with the -timezone option to the clock command (or, equivalently, by -gmt 1).
  3. A time zone specified in an environment variable TCL_TZ.
  4. A time zone specified in an environment variable TZ.
  5. The local time zone from the Control Panel on Windows systems.
  6. The C library's idea of the local time zone, as defined by the mktime and localtime functions.

Now, in case [1] only, the string gets tested to see if it's one of these iconic little guys:

gmt     ut      utc     bst     wet     wat     at
nft     nst     ndt     ast     adt     est     edt
cst     cdt     mst     mdt     pst     pdt     yst
ydt     hst     hdt     cat     ahst    nt      idlw
cet     cest    met     mewt    mest    swt     sst
eet     eest    bt      it      zp4     zp5     ist
zp6     wast    wadt    jt      cct     jst     cast
cadt    east    eadt    gst     nzt     nzst    nzdt
idle

If it is a string in that list, it designates a known time zone, and it gets interpreted as such. periodt. πŸ’…

For time zones in case [1] that don't match any of the above strings, and always for cases [2]–[6], the following rules apply:

  • If the time zone begins with a colon, it's one of a standardized list of names like :America/New_York that give the rules for various locales. A complete list of the location names is too lengthy to be listed here. On most Tcl installations, the definitions of the locations are to be found in named files in the directory /no_backup/tools/lib/tcl9.0/clock/tzdata. On some Unix systems, these files are omitted, and the definitions are instead obtained from system files in /usr/share/zoneinfo, /usr/share/lib/zoneinfo or /usr/local/etc/zoneinfo. As a special case, the name :localtime refers to the local time zone as defined by the C library. πŸ—‚οΈ
  • A time zone string consisting of a plus or minus sign followed by four or six decimal digits is interpreted as an offset in hours, minutes, and seconds (if six digits are present) from UTC. The plus sign denotes a sign east of Greenwich; the minus sign one west of Greenwich. βž•βž–
  • A time zone string conforming to the Posix specification of the TZ environment variable will be recognized. The specification may be found at https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html.
  • If the Posix time zone string contains a DST (Daylight Savings Time) part, but doesn't contain a rule stating when DST starts or ends, then default rules are used. For Timezones with an offset between 0 and +12, the current European/Russian rules are used, otherwise the current US rules are used. In Europe (offset +0 to +2) the switch to summertime is done each last Sunday in March at 1:00 GMT, and the switch back is each last Sunday in October at 2:00 GMT. In Russia (offset +3 to +12), the switch dates are the same, only the switch to summertime is at 2:00 local time, and the switch back is at 3:00 local time in all time zones. The US switch to summertime takes place each second Sunday in March at 2:00 local time, and the switch back is each first Sunday in November at 3:00 local time. These default rules mean that in all European, Russian and US (or compatible) time zones, DST calculations will be correct for dates in 2007 and later, unless in the future the rules change again. ⏰ (and yeah, "unless the rules change again" is doing a lot of heavy lifting there, bestie, but that's literally what it says)
  • Any other time zone string is processed by prefixing a colon and attempting to use it as a location name, as above.

πŸ—£οΈ LOCALIZATION

Devs who wanna localize the date and time formatting and parsing, this one's for you: you're referred to https://tip.tcl-lang.org/173 for a specification. πŸ’–


πŸ•°οΈ FREE FORM SCAN

So if clock scan gets invoked without a -format option, it requests a free-form scan. And bestie… this form of scan is deprecated. 🚨

Why, you ask? Because there are too many ambiguities. (Does the string "2000" represent a year, a time of day, or a quantity? genuinely no one knows 😭) No set of rules for interpreting free-form dates and times has been found to give unsurprising results in all cases.

If free-form scan is used, only the -base and -gmt options are accepted. The -timezone and -locale options will result in an error if -format is not supplied.

For the benefit of users who need to understand legacy code that uses free-form scan, the documentation for how free-form scan interprets a string is included here:

If only a time is specified, the current date is assumed. If the inputString does not contain a time zone mnemonic, the local time zone is assumed, unless the -gmt argument is true, in which case the clock value is calculated assuming that the specified time is relative to Greenwich Mean Time. -gmt, if specified, affects only the computed time value; it does not impact the interpretation of -base.

If the -base flag is specified, the next argument should contain an integer clock value. Only the date in this value is used, not the time. This is useful for determining the time on a specific day or doing other date-relative conversions. πŸ—“οΈ

The inputString argument consists of zero or more specifications of the following form:

  • time β€” A time of day, which is of the form: hh?:mm?:ss?? ?meridian? ?zone? or hhmm ?meridian? ?zone?. If no meridian is specified, hh is interpreted on a 24-hour clock. The "24:00" and "24:00:00" formats (with or without colon) are supported only if no meridian is specified.
  • date β€” A specific month and day with optional year. The acceptable formats are mm/dd?/yy?, monthname dd?, yy?, day, dd monthname ?yy?, dd monthname yy, ?CC?yymmdd, and dd-monthname-?CC?yy. The default year is the current year. If the year is less than 100, we treat the years 00-68 as 2000-2068 and the years 69-99 as 1969-1999. Not all platforms can represent the years 38-70, so an error may result if these years are used. πŸ™ˆ
  • ISO 8601 point-in-time β€” An ISO 8601 point-in-time specification, such as CCyymmddThhmmss, where T is the literal "T", CCyymmdd hhmmss, CCyymmddThh:mm:ss, or CCyy-mm-ddThh:mm:ss. Note that only these four formats are accepted. The command does not accept the full range of point-in-time specifications specified in ISO8601. For example, leap seconds are not supported. The "24:00" and "24:00:00" formats (with or without colon) are supported. Other formats can be recognized by giving an explicit -format option to the clock scan command.
  • relative time β€” A specification relative to the current time. The format is number unit. Acceptable units are year, fortnight, month, week, day, hour, minute (or min), and second (or sec). The unit can be specified as a singular or plural, as in 3 weeks. These modifiers may also be specified: tomorrow, yesterday, today, now, last, this, next, ago. ✨

The actual date is calculated according to the following steps:

  1. First, any absolute date and/or time is processed and converted.
  2. Using that time as the base, day-of-week specifications are added.
  3. Next, relative specifications are used.
  4. If a date or day is specified, and no absolute or relative time is given, midnight is used.
  5. Finally, a correction is applied so that the correct hour of the day is produced after allowing for daylight savings time differences and the correct date is given when going from the end of a long month to a short month.

The precedence of the applying of single tokens resp. which sequence will be used by calculating of the time is complex, e. g. heavily dependent on the precision of type of the token.

In example below the second date-string contains "next January", therefore it results in next year but in January. And third date-string besides "January" contains also additionally "Fri", so it results in the nearest Friday. Thus both win before "385 days" resp. make it more precise, because of higher precision of this token types. πŸ”₯

% clock format [clock scan "5 years 18 months 385 days" -base 0 -gmt 1] -gmt 1
Thu Jul 21 00:00:00 GMT 1977
% clock format [clock scan "5 years 18 months 385 days next January" -base 0 -gmt 1] -gmt 1
Sat Jan 21 00:00:00 GMT 1978
% clock format [clock scan "5 years 18 months 385 days next January Fri" -base 0 -gmt 1] -gmt 1
Fri Jan 27 00:00:00 GMT 1978

πŸ‘€ SEE ALSO


πŸ”‘ KEYWORDS

clock, date, time


Copyright Β© 2004 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.


and that's the whole thing, bestie!! πŸŽ€ this lil masterpiece ships with Tcl 8.5, and it's the clock(n) page β€” like, the moment where the Tcl 8.5 era and clock(n) meet at the bottom of the terminal and we all clap. πŸ’–βœ¨ go forth and never, ever use free-form scan. love u, bye!! πŸ‘‘πŸ¦‹

πŸ“¦ where this page comes from