Community discussions

 
User avatar
phistrom
just joined
Topic Author
Posts: 8
Joined: Sat Mar 11, 2017 8:45 pm
Location: Texas

Day of the Week and More

Sun Jul 14, 2019 6:37 am

I wrote a script that will hopefully be of use to people who need common date functions like finding out what day of the week it is.
It creates a function that you can call that gives you several convenient variables for that point in time. You run this script only once, and then refer to the global variable from other scripts or on the terminal using $datetime. The function returns an array with keys similar to the strptime/strftime function found in C, Python, and PHP.

To get the current day of the week, run this script, and then from the terminal you can type:
:put ([$datetime]->"w")
The result will be 0 for Sunday, 1 for Monday, and 6 for Saturday. The result is always for the moment you called the function.
If you'd like something more human, you could also use:
:put ([$datetime]->"A")
The result will be "Sunday", "Monday", ... "Saturday", depending on when you call the function.

To use the $datetime function in a script, you will need to declare the global variable. After that, you will probably want to call it and store the result in a variable. Then you can pull the data you need out of the array stored in that variable.

:global $datetime
# use square brackets around $datetime variable to execute the function
:local currentTime [$datetime]
# $currentTime is now an array of useful date and time information about the moment it was called
# print a convenient string of the format "YYYY-mm-dd"; great for file names that are sortable by date!
:put ($currentTime->"ymd")
# print the current time zone
:put ($currentTime->"Z")

See the README.md on Github for more information.

create-datetime-function.rsc:
:global datetime do={

    # PART 1 - THE BASICS

    :local months {
        "jan"="01"
        "feb"="02"
        "mar"="03"
        "apr"="04"
        "may"="05"
        "jun"="06"
        "jul"="07"
        "aug"="08"
        "sep"="09"
        "oct"="10"
        "nov"="11"
        "dec"="12"
    }

    :local dNames {"Sunday"; "Monday"; "Tuesday"; "Wednesday"; "Thursday"; "Friday"; "Saturday"}

    :local dt
    :local ti

    # this loop protects in the rare event we hit midnight between getting the date and time
    do {
        :set dt [/system clock get date]
        :set ti [/system clock get time]
    } while=($dt != [/system clock get date])

    :local b [:pick $dt 0 3 ]
    :local Y [:pick $dt 7 11 ]
    :local y [:pick $dt 9 11]
    :local m ($months->$b)
    :local d [:pick $dt 4 6]
    :local H [:pick $ti 0 2]
    # :local M [:pick $ti 3 5]
    # :local S [:pick $ti 6 8]
    # :local ymd "$Y-$m-$d"
    :local I ($H % 12)

    :if ($I = 0) do={
        :set I 12
    }

    :if ([:len $I] < 2) do={
        :set I ("0$I")
    }

    :local p
    :if ($H < 12) do={
        :set p "am"
    } else={
        :set p "pm"
    }

    # PART 2 - CREATE GMT OFFSET STRING

    :local oInt [/system clock get gmt-offset]
    :local oSign

    # GMT offset is returned as an unsigned integer containing a signed integer
    # so for negative numbers, it comes out as 4 billion instead of, say -18000
    # Additionally, the bitwise NOT operator doesn't work for numbers so we 
    # have to do this ugly thing here
    :if ($oInt > 2147483647) do={
        :set oInt (4294967296 - $oInt)
        :set oSign "-"
    } else={
        :set oSign "+"
    }

    # GMT Offset Hours
    :local oHrs ($oInt / 3600)
    # GMT Offset Minutes
    :local oMin (($oInt % 3600) / 60)

    :if ([:len $oHrs] < 2) do={
        :set oHrs ("0$oHrs")
    }

    :if ([:len $oMin] < 2) do={
        :set oMin ("0$oMin")
    }

    :local z "$oSign$oHrs$oMin"

    # PART 3 - DAY OF THE WEEK CALCULATION
    # this entire section inspired by https://cs.uwaterloo.ca/~alopez-o/math-faq/node73.html

    :local leapYear ( (($Y % 4) = 0) && ( (($Y % 100) != 0) || (($Y % 400) = 0) ) )

    :local monthKeyVal {1; 4; 4; 0; 2; 5; 0; 3; 6; 1; 4; 6}

    :local mkv ($monthKeyVal->($m-1))

    # January and February of a leap year get special treatment
    :if ( $leapYear && ( $m <= 2 ) ) do={
        :set mkv ($mkv - 1)
    }
    
    :local w ( (($y / 4) + $d) + $mkv )
    :if ($Y >= 2000) do={
        :set w ($w + 6)
    }
    :set w ((($w + $y) - 1) % 7)

    :local A ($dNames->w)
    :local a [:pick $A 0 3]

    # PART 4 - RETURN the results as an dictionary/array

    :local dtobject {
        "b"=$b
        "m"=$m
        "d"=$d
        "Y"=$Y
        "y"=$y
        "time"=$ti
        "H"=$H
        "M"=[:pick $ti 3 5]
        "S"=[:pick $ti 6 8]
        "date"="$Y-$m-$d"
        "I"=$I
        "p"=$p
        "z"=$z
        "w"=$w
        "A"=$A
        "a"=$a
        "Z"=[/system clock get time-zone-name]
    }

    :return $dtobject
}
The source code is also hosted on GitHub.


It has only been tested on 6.45.1 so far so feedback is appreciated.
MTCNA, MTCRE

Who is online

Users browsing this forum: No registered users and 15 guests