Swatch Internet Time or .beat time is a decimal time format without time zones. It was introduced by the Swatch corporation to promote their "Beat" watches. Some products released around the year 2000 have integrated support for .beat time, as does the programming language PHP.
dbohdan 2021-02-10: The following module can convert a clock seconds timestamp to .beat time and .beat time to seconds since midnight in UTC. It also works as a command line utility to display Swatch Internet Time. It is compatible with Jim Tcl.
#! /usr/bin/env tclsh # An Internet Time (.beat time) and general decimal time library. # Copyright (c) 2021 D. Bohdan. # License: MIT. namespace eval beat { variable version 0.5.0 # [catch] for Jim Tcl compatibility. catch { namespace export format scan *-to-* namespace ensemble create } } # Epoch time in seconds -> .beats. proc beat::format t { # Add an hour to go from UTC to UTC+1 (CET). seconds-to-decimal [expr { ($t + 3600) % 86400 }] } # .beats -> seconds since midnight in UTC. proc beat::scan beats { expr { ([decimal-to-seconds $beats] - 3600) % 86400 } } proc beat::seconds-to-decimal {s {unitsPerDay 1000}} { expr { int($s * $unitsPerDay / 86400.0) } } proc beat::decimal-to-seconds {dec {unitsPerDay 1000}} { expr { int(ceil($dec * 86400.0 / $unitsPerDay)) } } proc beat::test {command reference {maxDiff 0}} { upvar 1 errors errors set within [expr { $maxDiff == 0 ? {} : " within $maxDiff" }] set value [uplevel 1 $command] if {abs($value - $reference) > $maxDiff} { lappend errors "\[$command\] -> $value instead of $reference$within" } } proc beat::run-tests {} { set ref { 1000000000 115 1100000000 523 1200000000 930 1300000000 337 1400000000 745 1500000000 152 1600000000 560 1700000000 967 1800000000 375 1900000000 782 2000000000 189 1612973550 717 } set errors {} dict for {timestamp beats} $ref { test [list format $timestamp] $beats test [list scan $beats] [expr { $timestamp % 86400 }] 86 } test [list seconds-to-decimal 48400 1000] 560 test [list seconds-to-decimal 48400 200] 112 test [list seconds-to-decimal 48400 100] 56 test [list seconds-to-decimal 48400 20] 11 test [list seconds-to-decimal 48400 10] 5 test [list decimal-to-seconds 560 1000] 48384 test [list decimal-to-seconds 112 200] 48384 test [list decimal-to-seconds 56 100] 48384 test [list decimal-to-seconds 11 20] 47520 test [list decimal-to-seconds 5 10] 43200 for {set i 0} {$i < 1000} {incr i} { test "seconds-to-decimal \[decimal-to-seconds $i\]" $i } for {set i 0} {$i < 86400} {incr i} { test "decimal-to-seconds \[seconds-to-decimal $i\]" $i 86 } if {$errors ne {}} { error "tests failed:\n[join $errors \n]" } } proc beat::usage {} { puts stderr "usage: [file tail [info script]] \[(timestamp|\"test\")\]" } proc beat::main argv { switch [llength $argv] { 0 { set timestamp [clock seconds] } 1 { if {$argv eq {test}} { run-tests exit 0 } set timestamp $argv if {![string is integer -strict $timestamp]} { usage exit 1 } } default { usage exit 1 } } puts [format $timestamp] } # If this is the main script... if {[info exists argv0] && ([file tail [info script]] eq [file tail $argv0])} { beat::main $argv }