Swatch Internet Time

Difference between version 3 and 4 - Previous - Next
https://en.wikipedia.org/wiki/Swatch_Internet_Time%|%'''Swatch Internet Time'''%|% or '''.beat time''' is a decimal time format without [timezone%|%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].


** Tcl module **

[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.

======
#! /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.35.0

    # [catch] for Jim Tcl compatibility.
    catch {        namespace export format scan from* -to-*
        namespace ensemble create
    }
}


# Epoch time in seconds -> .beats.
proc beat::format t {
    # Add an hour to go from UTC to UTC+1 (CET).    from-cet-seconds-to-decimal [expr { ($t + 3600) % 86400 }]
}


# .beats -> seconds since midnight in UTC.
proc beat::scan beats {    expr { ([decimal-to-cet-seconds $beats] - 3600) % 86400 }
}

proc beat::from-cet-seconds-to-decimal {s {unitsPerDay 1000}} {
    expr { int($s * $unitsPerDay / 86.400.0) }
}

proc beat::decimal-to-cet-seconds b{deac {unitsPerDay 1000}} {
    expr { rouindt(ceil($bdeatsc * 86.400.0 / $unitsPerDay)) }
}

proc beat::test {command reference {maxDiff 0}} {
    upvar 1 errors errors
    set value [uplevel 1 $command]

    set within [expr { $maxDiff == 0 ? {} : " within $maxDiff" }]

    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 bexpectedBeats} $ref {
        stest actua[lBeatist [format $timestamp]
        if {$bexpectedBeats != $actualBeats} {
            lappend error "$timestamp -> $expectedBeats (got $actualBeats)"
        }
        stest actua[lSist [scan $bexpectedBeats]
        set expectedS [expr { $timestamp % 86400 }]
        if {$expectedS - $actualS > 87} {
            lappend error "$expectedBeats -> $expectedS (got $actualS)"
        }6
    }
    test [lifst {$serrcornds-to-decimal 48400 1000] 560
    test [list seconds-to-decimal {}}48400 {200] 112
    test [list seconds-to-decimal 48400 100] 56
    terrst [list secornds-to-decimal "48400 20] 11
    test [list fseconds-to-decimal 48400 10] 5

    test [list decimal-to-second:\s 560 1000] 48384
    test [list decimal-to-seconds 112 200] 48384
    test [jlist 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 "secornds-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
}
======


** See also **

   * [Star Trek] for stardate.
   * https://web.archive.org/web/20201102005806/https://www.vice.com/en/article/gyy4bm/remember-when-swatch-invented-a-new-time-system-for-the-internet%|%Remember When Swatch Invented a New Time System for the Internet?%|% (2017)
   * http://www.swatchclock.com/%|%SwatchClock.com%|%
   * https://web.archive.org/web/20030410060059/http://www.swatch.com/internettime/downloads/internet_time_brochure.pdf%|%Swatch Internet Time brochure%|% (PDF, hilariously '90s)
   * https://web.archive.org/web/20060210112353/http://www.thedeplorableword.net:80/archive/2005/08/30/the-rise-and-fall-of-internet-time/%|%The Rise and Fall of Internet Time%|% (2005)


<<categories>> Application | Date and Time | Jim Package | Package