time parsing in 7.1

I noticed the new

:timestamp

function in v7.1 and, although I don’t have a use for it yet I immediately thought of converting the string it returns to a raw number of seconds…

Really, I just thought this little diddy might be useful for someone else so I’m sharing it here

:global unixT2S do={
    :local time2parse [:timestamp]
    :local w [:find $time2parse "w"]
    :local d [:find $time2parse "d"]
    :local c [:find $time2parse ":"]
    :local p [:find $time2parse "."]
    :local weeks [:pick $time2parse 0 [$w]]
    :set $weeks ($weeks * 604800) 
    :local days [:pick $time2parse ($w + 1) $d]
    :set days ($days * 86400)
    :local hours [:pick $time2parse ($d + 1) $c]
    :set hours ($hours * 3600)
    :local minutes [:pick $time2parse ($c + 1) [:find $time2parse ($c + 3)]]
    :set minutes ($minutes * 60)
    :local seconds [:pick $time2parse ($c + 4) $p]
    :local nanoseconds [:pick $time2parse ($p + 1) [:len $time2parse]]

   # rawtime returns a number but is only accurate to the second
   # precisetime returns a string but gives full nanosecond accuracy
   # uncomment which one you would like returned
    :local rawtime ($weeks+$days+$hours+$minutes+$seconds)
    :return $rawtime
    :local precisetime ("$rawtime"."."."$nanoseconds")
    #:return $precisetime
}

Interesting.
I have used time in a script here http://forum.mikrotik.com/t/black-list-for-failed-login-to-ipsec-vpn/130090/4 to get a 5 min window.
Problem with the standard time function is that it only gives hour, but when it passes midnight it uses full date/time.
This may resolve it. Have requested MT for a full epoch time system.

I stumbled across :timestamp myself. Found this posting. Since there is no “date” type, guess “2711w6d17:53:35.252065073” is result if you only have time (and some hidden “time range” type like 00:00:00-1d in /ip/kid-control).

Imagine, Mikrotik ain’t reinventing the wheel, or time :wink:… So UNIX epoch does seem to be Jan 1, 1970. But @Jotne is right, clarity be good here – issue of “leap seconds” and “leap years” to consider. But seems there are using 86400 seconds per day, include leap days – but just a guess since the 22 minutes off from /system/clock is what I’m showing using @deadcat’s function.

Assuming it really just converting /system/clock to a UNIX-based time int (and then display as humanized 1000w10d… string to display in CLI)… if so, what effect does changing TZ have, or should have? e.g. good to know if it’s possible the [:timestamp] value could move backwards with the /system/clock/time-zone changes (or NTP/etc time changes) etc. since an “atomic time” is actually what you may want with something called “:timestamp” (although if atomic time counter is what you want, /system/resource/uptime does same non-adjusted/linear time.

But using @deadkat function, with /system/ssh to Mac with date -r <seconds>, it seems it ignores leap seconds from the 1970 epoch, but respect leap years. This makes since since it’s original definition of time_t.

/system/ssh address=192.168.x.y user=usr command="date +%s"
# 1640195280
:put [$unixT2S]
# 1640192640
/system/ssh address=192.168.x.y user=usr command="date -r $([$unixT2S])"
# Wed Dec 22 09:02:46 PST 2021
:put [/system/clock/get date]
# dec/22/2021
:put [/system/clock/get time]
# 09:24:52

Note: the time is off by 22 minutes. If right, hard to now. Pretty sure the Mac doing the “data -r” via ssh IS applying leap seconds etc. per man page.

On top at least some reference to the command…what’s seeming missing is :tonum doing what @deadkat function does:

:put [:tonum [:timestamp]]

or, :timestamp just returning a num (like Date.now() in JavaScript), then

:tostr [:timestamp]

get you the “week 1970 epoch” it does now: 2711w6d17:53:35.252065073

Obviously this isn’t a critical issue… just the CLI/ROS script is more like a crossword puzzle of types oddities. Since I was curious, wrote up what I found.

Good new function

:timestamp

But function returns a time type.

If you want to convert time type to number type - function

:tonum

is bugged

[:tonum [:timestamp]]

got nil…
hovever

[:totime ANYNUMBER]

work correctly

I have a script with function to correct convert time to number (integer unix timestamp seconds):

:global timetonum do={
    :local time2parse [ :timestamp ];
    :if ( [ :typeof $1 ] != "nil" ) do={
        :if ( [ :typeof [ :totime $1 ] ] = "time" ) do={
            :set time2parse [ :totime $1 ];
        };
    };

    :local weeks 0;
    :if ( [ :typeof [ :find $time2parse "w" ] ] != "nil" ) do={ :set weeks [ :pick $time2parse 0 [ :find $time2parse "w" ] ]; };

    :local days 0; :local startpos 0;
    :if ( $weeks !=0 ) do={ :set startpos ( [ :find $time2parse "w" ] + 1 ); };
    :if ( [ :typeof [ :find $time2parse "d" ] ] != "nil" ) do={ :set days [ :pick $time2parse $startpos [ :find $time2parse "d" ] ]; };

    :local hours [ :pick $time2parse ( [ :find $time2parse ":" ] - 2 ) [ :find $time2parse ":" ] ];

    :local minutes [ :pick $time2parse ( [ :find $time2parse ":" ] + 1 ) ( [ :find $time2parse ":" ] + 3 ) ];

    :local seconds [ :pick $time2parse ( [ :find $time2parse ":" ] + 4 ) ( [ :find $time2parse ":" ] + 6 ) ];

    :return ( ( $weeks * 604800 ) + ( $days * 86400 ) + ( $hours * 3600 ) + ( $minutes * 60 ) + $seconds );
};

Usage:

:put [$timetonum]

got integer timestamp

:put [$timetonum 1d1h2s]

got converting specified time to integer

:timestamp should return time since epoch, where epoch is January 1, 1970 not counting leap seconds

Good to know!

Maybe one day :tonum work with a time type to get “tick count” from :timestamp. Or, better still some option to :timestamp like type=num|str or format=“%s” :slight_smile:

What I don’t understand is how MikroTik can watch for years, how people have to write crazy long scripts for basic operations, and not think “hmm, maybe we could add some functions for that?” (to be fair, they did have that thought, but didn’t get beyond that). Isn’t it obvious enough that such functions would be useful and appreciated? Regarding time, why can’t we do things like [:totime “2022-06-02 04:15:30”], [:dateformat “Y-m-d H:i:s” [:timestamp]] (borrow the format e.g. from PHP’s date() function), etc?

MikroTik must implement EVERYWHERE ISO:8601 date and time, instead of dozen of different modes to show date and time,
and still maintain working "Epoch" everywhere
Instead to use abbreviated dates on logs or different Jun/JUN/jun on various fields and 3 different types of data on logs, just for example
and why do not use logical / sortable dates like 2022/06/02...

Examples of ISO:8601 date and time:
2022-06-02T21:10:26+00:00 (Great Britain)

2022-06-02T21:10:26Z (UTC)

2022-06-02T23:10:26+02:00 (Italy)

:toisodatetime [:timestamp]
= 2022-06-02T21:10:26Z

:todatetime [:timestamp]
= 2022/06/02 21:10:26

0 is time offset on minutes, default 0 if omitted for UTC

[:toepoch "2022/06/02 21:10:26" 0]
= 1654204226

It’s an Epoch-less!