I’ve need to do some date/time comparisons on RouterOS 6.40.9, and as new scripting commands to make this easier don’t yet exist–see the “Built in function library” thread–I did it the hard way.
This script provides three basic timestamp functions. All three use name-based arguments, not positional.
- getUnixTimestamp date time [offset]
- getNow
- getFileTimestamp filename
More documentation appears in comments in the code below:
NOTE: Updated to version 2.0 to get the old code working as RouterOS has evolved over the years changing the date format output from mmm/DD/YYYY to YYYY-MM-DD which broke the old 1.0 and 1.1 versions. The new 2.0 version should work with RouterOS 7.x–or at least works on my 7.18.2 test MikroTik device. – Aaron (07 APR 2025)
## -----
## timestamp - a few utility functions for handling date + time timestamps as Unix-style
## integer timestamps (seconds since the midnight Jan. 1, 1970 GMT epoch)
##
## Version 2.0
##
## Written by Aaron D. Gifford
## https://www.aarongifford.com/
##
## The above author, and original copyright owner, InfoWest, Inc. hereby place this code in the
## PUBLIC DOMAIN. You may use this code in any way. You may alter it. Redistribute it or any
## derivitave with NO requirements whatsoever. You may remove this notice or remove the
## author's name. You could even claim you wrote it (though that's not very cool). Attribution
## or acknowledgement is appreciated, but not required. Have fun! (NO WARRANTIES, etc.)
## -----
## FUNCTION:
## getUnixTimestamp date="1970-01-01" time="00:00:00" [offset=0]
## * date is a string in the form "YYYY-MM-DD"
## * time is a string in the form "HH:MM:SS" (24-hour clock)
## * offset is an OPTIONAL signed integer number of seconds east of GMT
## such that a positive offset is for zones east of GMT and a negative
## offset is for zones west of GMT. IF NOT included, the script will
## retrieve the currently ative device offset using:
## /system clock get gmt-offset
##
## Example use:
## {
## :local timestamp [$getUnixTimestamp time=[/system clock get date] date=[/system clock get time]]
## ...
##
## RETURNS a Unix-style timestamp, an integer number of seconds elapsed since the Unix epoch
## (01 JAN 1970 GMT). Hopefully MikroTik will soon add a system function to return a timestamp
## directly, making this obsolete.
##
## FUNCTION:
## getNow
##
## RETURNS the same thing as doing:
## $getUnixTimestamp time=[/system clock get date] date=[/system clock get time]
##
## FUNCTION:
## getFileTimestamp fname="filename.txt"
## * fname - the name/path of the file for which a creation timestamp will be retrieved
##
## RETURNS:
## Unix-style timestamp of creation date/time for file OR returns false if file was not found
##
:global getUnixTimestamp do={
:local timestr [:tostr $time]
:local datestr [:tostr $date]
:local hour [:tonum [:pick $timestr 0 2]]
:local min [:tonum [:pick $timestr 3 5]]
:local sec [:tonum [:pick $timestr 6 8]]
:local timestamp (($hour*3600) + ($min*60) + $sec)
:local year [:tonum [:pick $datestr 0 4]]
:local mon ([:tonum [:pick $datestr 5 7]]-1)
:local day ([:tonum [:pick $datestr 8 11]]-1)
## NOTE: 1 was subtracted from both day and month to make them zero-based
## For each month already passed, account for the days passed (ignoring Feb. 29th for now):
:local i 0
:while ($i < $mon) do={
:local mdays [:pick {31;28;31;30;31;30;31;31;30;31;30;31} $i]
:set timestamp ($mdays * 86400 + $timestamp)
:set i ($i+1)
}
## Account for the number of days already passed for the current month:
:set timestamp (86400*$day+$timestamp)
## For each year completed since the epoch, include 365 days worth of seconds (again ignoring leap years):
:set timestamp (($year-1970)*31536000+$timestamp)
## Account for Feb. 29 additionl days in leap years already completed:
:set i 1970
:while ($i<$year) do={
:if (($i+3)/4 = $i/4 && (($i+99)/100 != $i/100 || ($i+399)/400 = $i/400)) do={
## REMEMBER: Leap years occur on years evenly divisible by 4 EXCEPT for those
## that are ALSO evenly divisible by 100 UNLESS the century year is ALSO
## divisible by 400 (in which case it IS a leap year after all):
:set timestamp (86400+$timestamp)
}
:set i ($i+1)
}
## IF the date in question is already past February, account for a leap day IF this year is
## a leap year too:
:if ($mon > 1 && ($year+3)/4 = $year/4 && (($year+99)/100 != $year/100 || ($year+399)/400 = $year/400)) do={
:set timestamp (86400+$timestamp)
}
## Account for time zone offset:
:local tzoffset $offset
:if ([:typeof $tzoffset] = "nothing") do={
:set tzoffset [/system clock get gmt-offset]
}
:if ($tzoffset > 2147483648) do={
## A VERY LARGE integer indicates that the offset is negative (west). Convert
## the offset and subtract the resulting negative integer from the timestamp
## (i.e. add the positive absolute value to the timestamp):
:set timestamp (4294967296-$tzoffset+$timestamp)
} else={
## A small integer indicates the offset is positive (east). Simply subtract
## it from the timestamp:
:set timestamp ($timestamp-$tzoffset)
}
:return $timestamp
}
:global getNow do={
:global getUnixTimestamp
:return [$getUnixTimestamp date=[/system clock get date] time=[/system clock get time]]
}
:global getFileTimestamp do={
:global getUnixTimestamp
:local fileid [/file find where name="$fname"]
:if ([:len $fileid]=0) do={
## No file found!
:return false
}
:local filets [/file/get value-name=last-modified $fileid]
:return [$getUnixTimestamp date=[:pick $filets 0 10] time=[:pick $filets 11 19]]
}
## The End
Enjoy!
-Astounding