Community discussions

MikroTik App
 
User avatar
diamuxin
Member
Member
Topic Author
Posts: 317
Joined: Thu Sep 09, 2021 5:46 pm
Location: Alhambra's City

Convert month to number on date (not typical)

Fri Nov 18, 2022 12:46 pm

Hi,

I want to understand how it works to convert the month of a date to a number. I have already seen several examples on the forum.

In this example it works fine:
{
:local dateUptime [/interface get [/interface find where name=pppoe-out1] last-link-up-time]
# Result format --> oct/27/2022 02:30:50
:local monthUp [:tostr ([:find "janfebmaraprmayjunjulaugsepoctnovdec" [:pick $dateUptime 0 3] ]/3+1)]
:if ([:tonum $monthUp]<10) do={:set monthUp "0$monthUp"}
:put $monthUp
# Result --> 10
}
What if the result would be like this? (this is an example with Spanish date)

How to construct the ":pick" ?
{
:local dateUptime "27/oct/2022 02:30:50"
:local monthUp [:tostr ([:find "janfebmaraprmayjunjulaugsepoctnovdec" [:pick $dateUptime 3 6] ]/?+?)]
:if ([:tonum $monthUp]<10) do={:set monthUp "0$monthUp"}
:put $monthUp
}
I would especially love to understand how it is done.

Thank you in advance.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11967
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Convert month to number on date (not typical)  [SOLVED]

Fri Nov 18, 2022 2:05 pm

I do not like the previous method, are not easily understandable.

I would especially love to understand how it is done.
First step, ignoring all the frills, what is get from "/system clock get date"?
A string that represent current RouterBOARD date (ignoring if is syncronized or not)
for example, today:

nov/18/2022

All parts are correctly readable with pick:

date code

nov/18/2022
0123456789AB
A = 10
B = 11
the syntax of pick is: take characters from the string from x to the previous of y
if we want the month must be picked from 0 to the previous of 3,
the same is valid for day (from 4 to the previous of 6) and for the year (from 7 to previous of 10):
:put "M: $[:pick [/system clock get date] 0 3]"
:put "D: $[:pick [/system clock get date] 4 6]"
:put "Y: $[:pick [/system clock get date] 7 11]"
But if you want the month as numerical value (as it must be)
because is more logical ans sortable the date 2022-11-18 (ISO) than the unsortable nov/18/2022 (English)
you must convert "nov" to numeric value.


First approach
(used from your example, here simplified)
:put ([:find "janfebmaraprmayjunjulaugsepoctnovdec" "nov" ] / 3 + 1)
search the position of "nov" inside one string,
divide for 3 that results, because each month are 3 characters log,
and add one, because for "jan" is (0 / 3 + 1) = 1
and calculate the month based on that position
for november is (30 / 3 + 1) = 11
First approach revised with my style, + 1 is not needed and return 0 only if the string provided is not a month:
:put ([:find "xxxjanfebmaraprmayjunjulaugsepoctnovdec" "nov" ] / 3)


Second approach, one of my methods: create one array, for each month name, you have the right number:
{
    :local arrMonths {an=1;eb=2;ar=3;pr=4;ay=5;un=6;ul=7;ug=8;ep=9;ct=10;ov=11;ec=12}
    :put ($arrMonths->"ov")
}
but why only "ov"???
Because this work on both mikrotik provided date: "Nov" or "nov", and each mont have different last two letters.
On this case :pick do not pick from 0 to 3, but from 1 to 3. I do not know if on any point is provided month names on all uppercase.
How work: the value associated with the name of the month is retrieved from the array, in this case the equivalent number.


Third approach, among those that I have invented, my favorite:
search inside a string end month letters on insensitive case.
Example for "nov", "Nov", "NOV" and... nOV. Obviously is not considered nOv, noV, NOv and NoV....
"ov" are the last two letters of "nov" and "Nov":
{
:local M ([:find "xxanebarprayunulugepctovecANEBARPRAYUNULUGEPCTOVEC" "ov" -1] / 2); :if ($M>12) do={:set M ($M - 12)}
:put $M
}
both lowercase and uppercase are present, and xx are a riempitive for not have "0" as results.
although all close together, there is no combination of letters that can be misunderstood
AN, for JAN, is 13 (26 / 2), so to get the correct number of the month, 12 must be subtracted when the number exceeds 12
For "ov": the string start on 22th character. Must be divided by 2 because each month have two letter and 0 have insignificative "xx" value.
(22 / 2) = 11



How add "0" in front of months 1 - 9 if is needed? (on Second approach just add 0 in front of 1 - 9 and put all inside "" like from 1 to "01"

example 1, my preferred: add 100 and pick the last 2 values,
example for september "9":
:put [:pick (100 + 9) 1 3]

example 2: if the value is less than 10, add 0: (used on your example)
example for september "9":
{
:local MM 9
:if ($MM < 10) do={:set MM "0$MM"}
:put $MM
}

example 3: if the length is less than 2, add 0:
example for september "9":
{
:local MM 9
:if ([:len $MM] < 2) do={:set MM "0$MM"}
:put $MM
}

example 4, add "0" and pick the last 2 values,
example for september "9":
{
:local MM 9
:local MM "0$MM"
:put [:pick $MM ([:len $MM] - 2) [:len $MM]]
}
Last edited by rextended on Fri Nov 18, 2022 2:59 pm, edited 6 times in total.
 
User avatar
diamuxin
Member
Member
Topic Author
Posts: 317
Joined: Thu Sep 09, 2021 5:46 pm
Location: Alhambra's City

Re: Convert month to number on date (not typical)

Fri Nov 18, 2022 2:47 pm

Very well explained.

I'm going to study and practice this afternoon.
As always, thank you very much @rextended.

BR.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11967
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Convert month to number on date (not typical)

Fri Nov 18, 2022 2:54 pm

Thanks

I'm going to study and practice this afternoon.
I end now to write, rewirte and modify parts, check now ;)


Check also the "full version" of the script here:
viewtopic.php?p=960070#p960070
 
User avatar
diamuxin
Member
Member
Topic Author
Posts: 317
Joined: Thu Sep 09, 2021 5:46 pm
Location: Alhambra's City

Re: Convert month to number on date (not typical)

Fri Nov 18, 2022 7:02 pm

Great! I understood everything. Thanks.
After testing I'll stick with this combination:
{
:local dateUptime "27/sep/2022 02:30:50"
:local monthUp ([:find "xxanebarprayunulugepctovecANEBARPRAYUNULUGEPCTOVEC" [:pick $dateUptime 4 6] -1] / 2); :if ($monthUp >12) do={:set monthUp ($monthUp - 12)}
:set monthUp [:pick (100 + $monthUp) 1 3]
:put $monthUp
}
Valid for 27/sep/2022 and 27/Sep/2022.

:D :D

EDIT: Is it advisable to use?

[:tostr ([:find "janfeb.........
and
:if ([:tonum $monthUp]<10)..........

BR
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11967
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Convert month to number on date (not typical)

Sat Nov 19, 2022 1:30 am

is also valid for SEP !!! (and sEP)

EDIT: Is it advisable to use?

[:tostr ([:find "janfeb.........
and
:if ([:tonum $monthUp]<10)..........
In some other cases, for examples when working with IPs, are required explicit conversion or not work as expected, but on this cases,

:pick everytime return a string, except when not used on one array (of array), and except when can not pick anything, and return "nil"
if pick is used on number, the conversion from number to string is implicit

:find everytime return a number (when find something, or return "nil")

$monthUp is already a number for sure (except when dateUptime is wrong) because is a result of :find,
convert again to number, is useless.

Who is online

Users browsing this forum: No registered users and 21 guests