Community discussions

MikroTik App
 
shaktipatil
just joined
Topic Author
Posts: 6
Joined: Wed Oct 25, 2017 2:30 pm

script to calculate next date

Wed Oct 25, 2017 2:44 pm

Hello all,

I need a help in script to calculate next date like below:

current or today's date: Oct/25/2017
grace days: 28
Next date:Nov/22/2017 (which i need to calculate programmatically)

Thanks
 
User avatar
BlackVS
Member Candidate
Member Candidate
Posts: 172
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: script to calculate next date

Fri Oct 27, 2017 4:10 pm

ROS scripting has ridiculous support for dates.
You can't add/substract them.
You need split you date on days, months, years and then do date arithmetic taking into consideration days in the months and leap years.
From one hand it is no difficult task for programmers, but admins usually not programmers %)

In few days I will make and upload needed for you script. Be patient %)
 
User avatar
BlackVS
Member Candidate
Member Candidate
Posts: 172
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: script to calculate next date  [SOLVED]

Fri Oct 27, 2017 5:21 pm

################################################################### func_shiftDate - add days to date
#  Input: date, days
#    date - "jan/1/2017"
#    days - number
# correct only for years >1918
################################################################### uncomment for testing
#:local date "jan/01/2100"
#:local days 2560
########################################
#:put "$date + $days"
:local mdays  {31;28;31;30;31;30;31;31;30;31;30;31}
:local months {"jan"=1;"feb"=2;"mar"=3;"apr"=4;"may"=5;"jun"=6;"jul"=7;"aug"=8;"sep"=9;"oct"=10;"nov"=11;"dec"=12}
:local monthr  {"jan";"feb";"mar";"apr";"may";"jun";"jul";"aug";"sep";"oct";"nov";"dec"}

:local dd  [:tonum [:pick $date 4 6]]
:local yy [:tonum [:pick $date 7 11]]
:local month [:pick $date 0 3]

:local mm (:$months->$month)
:set dd ($dd+$days)

:local dm [:pick $mdays ($mm-1)]
:if ($mm=2 && (($yy&3=0 && ($yy/100*100 != $yy)) || $yy/400*400=$yy) ) do={ :set dm 29 }

:while ($dd>$dm) do={
  :set dd ($dd-$dm)
  :set mm ($mm+1)
  :if ($mm>12) do={
    :set mm 1
    :set yy ($yy+1)
  }
 :set dm [:pick $mdays ($mm-1)]
 :if ($mm=2 &&  (($yy&3=0 && ($yy/100*100 != $yy)) || $yy/400*400=$yy) ) do={ :set dm 29 }
};
:local res "$[:pick $monthr ($mm-1)]/"
:if ($dd<10) do={ :set res ($res."0") }
:set $res "$res$dd/$yy"
:return $res
Not fully tested yet.
To use script import it to your script and use as usual function:
:local shiftDate [:parse [/system script get func_shiftDate source]]
:put [$shiftDate date="jan/01/2017" days=256]
You should get "sep/14/2017"
To test any online calculator can be used, for example https://www.timeanddate.com/date/dateadd.html
PS: days in months calculated correct only for >1918. But we may simplify little bit calculations if restrict years to 2001..2399 or even to 2001...2099.
 
shaktipatil
just joined
Topic Author
Posts: 6
Joined: Wed Oct 25, 2017 2:30 pm

Re: script to calculate next date

Sat Oct 28, 2017 1:29 pm

################################################################### func_shiftDate - add days to date
#  Input: date, days
#    date - "jan/1/2017"
#    days - number
# correct only for years >1918
################################################################### uncomment for testing
#:local date "jan/01/2100"
#:local days 2560
########################################
#:put "$date + $days"
:local mdays  {31;28;31;30;31;30;31;31;30;31;30;31}
:local months {"jan"=1;"feb"=2;"mar"=3;"apr"=4;"may"=5;"jun"=6;"jul"=7;"aug"=8;"sep"=9;"oct"=10;"nov"=11;"dec"=12}
:local monthr  {"jan";"feb";"mar";"apr";"may";"jun";"jul";"aug";"sep";"oct";"nov";"dec"}

:local dd  [:tonum [:pick $date 4 6]]
:local yy [:tonum [:pick $date 7 11]]
:local month [:pick $date 0 3]

:local mm (:$months->$month)
:set dd ($dd+$days)

:local dm [:pick $mdays ($mm-1)]
:if ($mm=2 && (($yy&3=0 && ($yy/100*100 != $yy)) || $yy/400*400=$yy) ) do={ :set dm 29 }

:while ($dd>$dm) do={
  :set dd ($dd-$dm)
  :set mm ($mm+1)
  :if ($mm>12) do={
    :set mm 1
    :set yy ($yy+1)
  }
 :set dm [:pick $mdays ($mm-1)]
 :if ($mm=2 &&  (($yy&3=0 && ($yy/100*100 != $yy)) || $yy/400*400=$yy) ) do={ :set dm 29 }
};
:local res "$[:pick $monthr ($mm-1)]/"
:if ($dd<10) do={ :set res ($res."0") }
:set $res "$res$dd/$yy"
:return $res
Not fully tested yet.
To use script import it to your script and use as usual function:
:local shiftDate [:parse [/system script get func_shiftDate source]]
:put [$shiftDate date="jan/01/2017" days=256]
You should get "sep/14/2017"
To test any online calculator can be used, for example https://www.timeanddate.com/date/dateadd.html
PS: days in months calculated correct only for >1918. But we may simplify little bit calculations if restrict years to 2001..2399 or even to 2001...2099.

Thank you so much, i will give it a try today.
 
shaktipatil
just joined
Topic Author
Posts: 6
Joined: Wed Oct 25, 2017 2:30 pm

Re: script to calculate next date

Sat Oct 28, 2017 2:22 pm

################################################################### func_shiftDate - add days to date
#  Input: date, days
#    date - "jan/1/2017"
#    days - number
# correct only for years >1918
################################################################### uncomment for testing
#:local date "jan/01/2100"
#:local days 2560
########################################
#:put "$date + $days"
:local mdays  {31;28;31;30;31;30;31;31;30;31;30;31}
:local months {"jan"=1;"feb"=2;"mar"=3;"apr"=4;"may"=5;"jun"=6;"jul"=7;"aug"=8;"sep"=9;"oct"=10;"nov"=11;"dec"=12}
:local monthr  {"jan";"feb";"mar";"apr";"may";"jun";"jul";"aug";"sep";"oct";"nov";"dec"}

:local dd  [:tonum [:pick $date 4 6]]
:local yy [:tonum [:pick $date 7 11]]
:local month [:pick $date 0 3]

:local mm (:$months->$month)
:set dd ($dd+$days)

:local dm [:pick $mdays ($mm-1)]
:if ($mm=2 && (($yy&3=0 && ($yy/100*100 != $yy)) || $yy/400*400=$yy) ) do={ :set dm 29 }

:while ($dd>$dm) do={
  :set dd ($dd-$dm)
  :set mm ($mm+1)
  :if ($mm>12) do={
    :set mm 1
    :set yy ($yy+1)
  }
 :set dm [:pick $mdays ($mm-1)]
 :if ($mm=2 &&  (($yy&3=0 && ($yy/100*100 != $yy)) || $yy/400*400=$yy) ) do={ :set dm 29 }
};
:local res "$[:pick $monthr ($mm-1)]/"
:if ($dd<10) do={ :set res ($res."0") }
:set $res "$res$dd/$yy"
:return $res
Not fully tested yet.
To use script import it to your script and use as usual function:
:local shiftDate [:parse [/system script get func_shiftDate source]]
:put [$shiftDate date="jan/01/2017" days=256]
You should get "sep/14/2017"
To test any online calculator can be used, for example https://www.timeanddate.com/date/dateadd.html
PS: days in months calculated correct only for >1918. But we may simplify little bit calculations if restrict years to 2001..2399 or even to 2001...2099.

Excellent scrip!!! working as expected!!! Many Many Thanks!!!
 
User avatar
akotlyar
just joined
Posts: 12
Joined: Wed Mar 09, 2016 8:09 am

Re: script to calculate next date

Mon Oct 30, 2017 3:13 pm

################################################################### func_shiftDate - add days to date
#  Input: date, days
#    date - "jan/1/2017"
#    days - number
# correct only for years >1918
################################################################### uncomment for testing
#:local date "jan/01/2100"
#:local days 2560
########################################
#:put "$date + $days"
:local mdays  {31;28;31;30;31;30;31;31;30;31;30;31}
:local months {"jan"=1;"feb"=2;"mar"=3;"apr"=4;"may"=5;"jun"=6;"jul"=7;"aug"=8;"sep"=9;"oct"=10;"nov"=11;"dec"=12}
:local monthr  {"jan";"feb";"mar";"apr";"may";"jun";"jul";"aug";"sep";"oct";"nov";"dec"}

:local dd  [:tonum [:pick $date 4 6]]
:local yy [:tonum [:pick $date 7 11]]
:local month [:pick $date 0 3]

:local mm (:$months->$month)
:set dd ($dd+$days)

:local dm [:pick $mdays ($mm-1)]
:if ($mm=2 && (($yy&3=0 && ($yy/100*100 != $yy)) || $yy/400*400=$yy) ) do={ :set dm 29 }

:while ($dd>$dm) do={
  :set dd ($dd-$dm)
  :set mm ($mm+1)
  :if ($mm>12) do={
    :set mm 1
    :set yy ($yy+1)
  }
 :set dm [:pick $mdays ($mm-1)]
 :if ($mm=2 &&  (($yy&3=0 && ($yy/100*100 != $yy)) || $yy/400*400=$yy) ) do={ :set dm 29 }
};
:local res "$[:pick $monthr ($mm-1)]/"
:if ($dd<10) do={ :set res ($res."0") }
:set $res "$res$dd/$yy"
:return $res
Not fully tested yet.
To use script import it to your script and use as usual function:
:local shiftDate [:parse [/system script get func_shiftDate source]]
:put [$shiftDate date="jan/01/2017" days=256]
You should get "sep/14/2017"
To test any online calculator can be used, for example https://www.timeanddate.com/date/dateadd.html
PS: days in months calculated correct only for >1918. But we may simplify little bit calculations if restrict years to 2001..2399 or even to 2001...2099.
Hello!
How i can get this result(sep/14/2017)? I tried all variables, and nothing - empty, for example :log info message="What output variable must be here?"
 
User avatar
BlackVS
Member Candidate
Member Candidate
Posts: 172
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: script to calculate next date

Mon Oct 30, 2017 4:41 pm

Hm...
Just create new script named func_shiftDate , insert into it code from above and call this script from you script as function.
https://wiki.mikrotik.com/wiki/Manual:S ... #Functions
 
User avatar
akotlyar
just joined
Posts: 12
Joined: Wed Mar 09, 2016 8:09 am

Re: script to calculate next date

Mon Oct 30, 2017 9:28 pm

Yes, I create two scripts:
1. First script - I copy func_shiftDate code and named script func_shiftDate.
2. Second script - named script4 :)
:local shiftDate [:parse [/system script get func_shiftDate source]]
:put [$shiftDate date="jan/01/2017" days=256]
:log info message="$shiftDate";

output:
(code)

Do you have some idea what i do wrong?
Thanks for your time.
 
User avatar
BlackVS
Member Candidate
Member Candidate
Posts: 172
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: script to calculate next date

Tue Oct 31, 2017 7:19 am

:put - outputs result to terminal, not to log
:log - outputs to log, not to terminal.
In your example you outputs new date to terminal and try output function's parsed code to log. That you see (code) in log.
If you wish insert any calculations\functions call into the string you must use "$[calculation]" notation.
I.e. if you wish output shifted date to log run this:
:local newDate [$shiftDate date="jan/01/2017" days=256]
:log info message="$newDate"
or just
:log info message="$[$shiftDate date="jan/01/2017" days=256]"
PS: due to shiftDate returns already string you may do even simpler:
:local newDate [$shiftDate date="jan/01/2017" days=256]
:log info message=$newDate
or
:log info message=[$shiftDate date="jan/01/2017" days=256]
I.e. it is no need to insert string into the string
 
User avatar
akotlyar
just joined
Posts: 12
Joined: Wed Mar 09, 2016 8:09 am

Re: script to calculate next date

Tue Oct 31, 2017 9:04 am

:put - outputs result to terminal, not to log
:log - outputs to log, not to terminal.
In your example you outputs new date to terminal and try output function's parsed code to log. That you see (code) in log.
If you wish insert any calculations\functions call into the string you must use "$[calculation]" notation.
I.e. if you wish output shifted date to log run this:
:local newDate [$shiftDate date="jan/01/2017" days=256]
:log info message="$newDate"
or just
:log info message="$[$shiftDate date="jan/01/2017" days=256]"
PS: due to shiftDate returns already string you may do even simpler:
:local newDate [$shiftDate date="jan/01/2017" days=256]
:log info message=$newDate
or
:log info message=[$shiftDate date="jan/01/2017" days=256]
I.e. it is no need to insert string into the string
Yes, it.s works! My fault, thank you!
 
User avatar
akotlyar
just joined
Posts: 12
Joined: Wed Mar 09, 2016 8:09 am

Re: script to calculate next date

Tue Oct 31, 2017 10:15 am

Do you planning add: subtraction?
Example: [$shiftDate date="jan/01/2017" days=-60]
 
User avatar
BlackVS
Member Candidate
Member Candidate
Posts: 172
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: script to calculate next date

Tue Oct 31, 2017 11:19 am

You read my mind %)
Yes, sure.
Also I'm planning to add dates comparison (<,>,==) and subtraction of dates (i.e. how much days between dates) to have full date arithmetic.
 
User avatar
BlackVS
Member Candidate
Member Candidate
Posts: 172
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: script to calculate next date

Wed Nov 01, 2017 10:11 am

 
MLR
just joined
Posts: 7
Joined: Tue Oct 17, 2023 10:11 am

Re: script to calculate next date

Sat Oct 28, 2023 6:25 pm

please update the script suitable to 7.10 OS update. Please
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11937
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: script to calculate next date

Sun Oct 29, 2023 3:33 am

Convert date/time to epoch:
viewtopic.php?p=994849#p994849

add the required numer of seconds,

Convert back epoch to datetime:
viewtopic.php?p=977170#p977170

On those days I have just the time to reply on this way.
When I have time (and I remember this) can I check, but also other forum members can check and fix...
 
MLR
just joined
Posts: 7
Joined: Tue Oct 17, 2023 10:11 am

Re: script to calculate next date

Sun Oct 29, 2023 3:50 pm

:global datetime2epoch do={
    :local dtime [:tostr $1]
    /system clock
    :local cyear [get date] ; :if ($cyear ~ "....-..-..") do={:set cyear [:pick $cyear 0 4]} else={:set cyear [:pick $cyear 7 11]}
    :if (([:len $dtime] = 10) or ([:len $dtime] = 11)) do={:set dtime "$dtime 00:00:00"}
    :if ([:len $dtime] = 15) do={:set dtime "$[:pick $dtime 0 6]/$cyear $[:pick $dtime 7 15]"}
    :if ([:len $dtime] = 14) do={:set dtime "$cyear-$[:pick $dtime 0 5] $[:pick $dtime 6 14]"}
    :if ([:len $dtime] =  8) do={:set dtime "$[get date] $dtime"}
    :if ([:tostr $1] = "") do={:set dtime ("$[get date] $[get time]")}
    :local vdate [:pick $dtime 0 [:find $dtime " " -1]]
    :local vtime [:pick $dtime ([:find $dtime " " -1] + 1) [:len $dtime]]
    :local vgmt  [get gmt-offset]; :if ($vgmt > 0x7FFFFFFF) do={:set vgmt ($vgmt - 0x100000000)}
    :if ($vgmt < 0) do={:set vgmt ($vgmt * -1)}
    :local arrm  [:toarray "0,0,31,59,90,120,151,181,212,243,273,304,334"]
    :local vdoff [:toarray "0,4,5,7,8,10"]
    :local MM    [:pick $vdate ($vdoff->2) ($vdoff->3)]
    :local M     [:tonum $MM]
    :if ($vdate ~ ".../../....") do={
        :set vdoff [:toarray "7,11,1,3,4,6"]
        :set M     ([:find "xxanebarprayunulugepctovecANEBARPRAYUNULUGEPCTOVEC" [:pick $vdate ($vdoff->2) ($vdoff->3)] -1] / 2)
        :if ($M>12) do={:set M ($M - 12)}
    }
    :local yyyy  [:pick $vdate ($vdoff->0) ($vdoff->1)] ; :if ((($yyyy - 1968) % 4) = 0) do={:set ($arrm->1) -1; :set ($arrm->2) 30}
    :local totd  ((($yyyy - 1970) * 365) + (($yyyy - 1968) / 4) + ($arrm->$M) + ([:pick $vdate ($vdoff->4) ($vdoff->5)] - 1))
    :return      (((((($totd * 24) + [:pick $vtime 0 2]) * 60) + [:pick $vtime 3 5]) * 60) + [:pick $vtime 6 8] - $vgmt)
}



      :local currDate [/system clock get date]
      :local currDateSeconds [$datetime2epoch $currDate]
      :local aDayinSeconds "86400"      
      :local DSR
      :set DSR ([:tonum $currDateSeconds]-[:tonum $aDayinSeconds]) #Deducted 86400 to get Previous Date. 



#########################################################################xxxxxxxxxxxxxxxxxxxxxxxxxxx




:global unixtodatetime do={
    :local ux [:tonum $1]
    :local Fzerofill do={:return [:pick (100 + $1) 1 3]}
    :local prMntDays [:toarray "0,0,31,59,90,120,151,181,212,243,273,304,334"]
    :local vgmt      [:tonum [/system clock get gmt-offset]]; :if ($vgmt > 0x7FFFFFFF) do={:set vgmt ($vgmt - 0x100000000)}
    :if ($vgmt < 0) do={:set vgmt ($vgmt * -1)}
    :local tzepoch   ($ux + $vgmt)
    :if ($tzepoch < 0) do={:set tzepoch 0} ; # unsupported negative unix epoch
    :local yearStart (1970 + ($tzepoch / 31536000))
    :local tmpbissex (($yearStart - 1968) / 4) ; :if ((($yearStart - 1968) % 4) = 0) do={:set ($prMntDays->1) -1 ; :set ($prMntDays->2) 30}
    :local tmpsec    ($tzepoch % 31536000)
    :local tmpdays   (($tmpsec / 86400) - $tmpbissex)
    :if (($tmpsec < (86400 * $tmpbissex)) and ((($yearStart - 1968) % 4) = 0)) do={
        :set tmpbissex ($tmpbissex - 1) ; :set ($prMntDays->1) 0 ; :set ($prMntDays->2) 31 ; :set tmpdays  ($tmpdays + 1)
    }
    :if ($tmpsec < (86400 * $tmpbissex)) do={:set yearStart ($yearStart - 1) ; :set tmpdays   ($tmpdays + 365)}
    :local mnthStart 12 ; :while (($prMntDays->$mnthStart) > $tmpdays) do={:set mnthStart ($mnthStart - 1)}
    :local dayStart  [$Fzerofill (($tmpdays + 1) - ($prMntDays->$mnthStart))]
    :local timeStart (00:00:00 + [:totime ($tmpsec % 86400)])
    :return "$yearStart/$[$Fzerofill $mnthStart]/$[$Fzerofill $dayStart] $timeStart"
}

:local YESTERDAY [$unixtodatetime $DSR]
This is for previous date. Adding 86400 to current date to get next date

Thanks you @rextended
 
User avatar
diamuxin
Member
Member
Posts: 311
Joined: Thu Sep 09, 2021 5:46 pm

Re: script to calculate next date

Sun Oct 29, 2023 5:35 pm

Another way to do it (based on @rextended functions)

example code

:global unixtodatetime do={
    :local ux [:tonum $1]
    :local Fzerofill do={:return [:pick (100 + $1) 1 3]}
    :local prMntDays [:toarray "0,0,31,59,90,120,151,181,212,243,273,304,334"]
    :local vgmt      [:tonum [/system clock get gmt-offset]]; :if ($vgmt > 0x7FFFFFFF) do={:set vgmt ($vgmt - 0x100000000)}
    :if ($vgmt < 0) do={:set vgmt ($vgmt * -1)}
    :local tzepoch   ($ux + $vgmt)
    :if ($tzepoch < 0) do={:set tzepoch 0} ; # unsupported negative unix epoch
    :local yearStart (1970 + ($tzepoch / 31536000))
    :local tmpbissex (($yearStart - 1968) / 4) ; :if ((($yearStart - 1968) % 4) = 0) do={:set ($prMntDays->1) -1 ; :set ($prMntDays->2) 30}
    :local tmpsec    ($tzepoch % 31536000)
    :local tmpdays   (($tmpsec / 86400) - $tmpbissex)
    :if (($tmpsec < (86400 * $tmpbissex)) and ((($yearStart - 1968) % 4) = 0)) do={
        :set tmpbissex ($tmpbissex - 1) ; :set ($prMntDays->1) 0 ; :set ($prMntDays->2) 31 ; :set tmpdays  ($tmpdays + 1)
    }
    :if ($tmpsec < (86400 * $tmpbissex)) do={:set yearStart ($yearStart - 1) ; :set tmpdays   ($tmpdays + 365)}
    :local mnthStart 12 ; :while (($prMntDays->$mnthStart) > $tmpdays) do={:set mnthStart ($mnthStart - 1)}
    :local dayStart  [$Fzerofill (($tmpdays + 1) - ($prMntDays->$mnthStart))]
    :local timeStart (00:00:00 + [:totime ($tmpsec % 86400)])
    :return "$yearStart/$[$Fzerofill $mnthStart]/$[$Fzerofill $dayStart] $timeStart"
}

:global timetoseconds do={
    :local inTime $1
    :local wPos   [:find $inTime "w" -1]
    :local dPos   [:find $inTime "d" -1]
    :local itLen  [:find $inTime "." -1] ; :if ([:typeof $itLen] = "nil") do={:set itLen [:len $inTime]}
    :local itSec  [:pick $inTime ($itLen - 2) $itLen]
    :local itMin  [:pick $inTime ($itLen - 5) ($itLen - 3)]
    :local itHou  [:pick $inTime ($itLen - 8) ($itLen - 6)]
    :local itDay  0
    :local itWee  0
    :if (([:typeof $wPos] = "nil") and ([:typeof $dPos] = "num")) do={:set itDay [:pick $inTime 0 $dPos] }
    :if (([:typeof $wPos] = "num") and ([:typeof $dPos] = "num")) do={:set itDay [:pick $inTime ($wPos + 1) $dPos] }
    :if  ([:typeof $wPos] = "num")                                do={:set itWee [:pick $inTime 0 $wPos] }
    :local totitSec ($itSec + (60 * $itMin) + (3600 * $itHou) + (86400 * $itDay) + (604800 * $itWee))
    :return $totitSec
}

# =======================

{
:global unixtodatetime
:global timetoseconds
:local  currDateSeconds [$timetoseconds [:timestamp]]
:local  aDayinSeconds "86400"      
:local  DSR ($currDateSeconds - $aDayinSeconds) ; #Deducted 86400 to get Previous Date. 
:local  YESTERDAY [$unixtodatetime $DSR]
:put $YESTERDAY
}
Result:  2023/10/28 16:30:04

Who is online

Users browsing this forum: No registered users and 33 guests