mIRC Homepage

$ctime(string) eval

Posted By: maroon

$ctime(string) eval - 03/10/19 02:42 PM

In $ctime(date string), if parm#1 containing a comma touching the year, it always evaluates the year as 1899. I encountered an RFC presenting a date like

String sDate = "Mar 25 2008, 12:06:30 GMT";

//var -s %a Mar 25 $rand(1601,9999) $+ , 12:06:30 , %b $ctime(%a) , %c $asctime(%b) , %d $gmt(%b)

Removing the $+ allows N to be calculated using the correct year. This behavior has changed across several versions.

//var -s %a Mar 25 2008, 12:06:30 , %b $ctime(%a) , %c $asctime(%b) , %d $gmt(%b)

In 7.57 this returns %b within year 1899
In 7.55 this returns %b as $null
In 6.35 this returns %b within correct year 2008
Posted By: Khaled

Re: $ctime(string) eval - 04/10/19 08:16 AM

Thanks for your bug report. A comma has never been valid input to this identifier. It should be returning $null in this case.

It looks like adding support for year range 1601 to 9999 in v7.55 has caused it to handle invalid input differently.

I will be changing this in the next beta so that 1) $null is returned for invalid input as before, and 2) commas are allowed as separators (unless someone can see an issue with backwards compatibility here...)
Posted By: maroon

Re: $ctime(string) eval - 04/10/19 02:15 PM

I can't think of lack of compatibility, unless someone somehow has an almost-a-date string they want to detect from a $null value.

Enabling comma as a delimiter would enable a very common date format

//var -s %a Mar 25, 2008 , %b $ctime(%a) , %c $asctime(%b)
//var -s %a March 25, 2008 , %b $ctime(%a) , %c $asctime(%b)

Looking at the page for https://en.wikipedia.org/wiki/Date_format_by_country
It would be crazy to try to support them all. I do see that the period is a common delimiter used by multiple countries. While mIRC is recognizing them in some formats, one I see used several places that's returning null is: (ddd|dddd) (d|dd). (mmm|mmmm) yyyy

//var -s %a Tuesday 25. Mar 2008 , %b $ctime(%a) , %c $asctime(%b)
Posted By: Raccoon

Re: $ctime(string) eval - 11/11/19 07:28 PM

Khaled: Could you give us an exhaustive list of primary date/time formats accepted as input to $ctime(), and then discuss the minor variations or deviations that will also be detected and accepted for each type? (It would assist me in framing the boundaries of this bug.)

The help file specifies the following four formats are recognized:

January 1 1970 00:00:00
3rd August 1987 3:46pm
21/4/72 1:30:37
Wed 1998-3-27 21:16

Of these formats, the user can deviate by omitting certain portions, such as the time (h:m:s) so that the current clock-time is assumed.

We can also see that these formats work:

3 Aug 1987  /* a variation of 3rd August 1987 3:46pm */
1998-03-27  /* a variation of Wed 1998-3-27 21:16 */

Are you using conventional C++ string array parsing, or regular expression parsing? If regular expression parsing, would you share the regex patterns with us?

If I were better informed of the different standard ISO date-time formats, I could articulate this post better, but I'm not there yet.

Also, did we arrive yet at a consensus to recognize $gmt(n) or $gmt($ctime(<date>)) as acceptable use of $gmt()? ((i think it should be))

One minor suggestion for added support for date-time recognition and assumption-making in $ctime():
If only a time value is passed, but no date value, then assume the current date. As in $ctime(13:00:59) or $ctime(5:00 p.m.) Below is pseudo-code.
This is similar in behavior to how $ctime() handles a date value with no time value, just in reverse, as it assumes the current time instead.

if ($regex($1-,/^[0-9:apm. ]+$/i)) { tokenize 32 $date $1- }
Posted By: Khaled

Re: $ctime(string) eval - 12/11/19 04:29 PM

The exhaustive list is in the help file. If you find that $ctime() is not fully documented, please let me know and I will update the help file.
Posted By: Raccoon

Re: $ctime(string) eval - 12/11/19 10:00 PM

This is what I believe I learned from fuzzing $ctime() with innumerous date/time strings.

Basically mIRC just reads from left-to-right trying to identify any date/time parts that it comes across, then fills in an internal variable for that given part.
Upon further inspection, mIRC performs at least 3 distinct passes to parse different values, so I'll segment this in order of those passes.
The order of these passes determines which time date parts will be overwritten if they occur twice in the string.

Any portion of the time and date can appear in ANY order, as long as all internal variables are filled (h m s optional).
Any portion of the time and date can appear multiple times, and it will overwrite previous values,

Internal variables are: Month, Date, Year, Hour, Minute, Second

Pass 1
If we encounter a number from 1 to 31, update our DATE variable.
If we encounter a number from 32 to 99 or 1601 to 9999, update our YEAR variable.
* years 32 to 99 are assumed 1900's.

Pass 2
If either structure d/d/d or d-d-d is encountered, as in 1/1/1 or 29-2-28
the center number is always the month,
try the left number as the day and the right number as the year,
if that's an invalid calendar date, then try the left number as the year and the right number as the day,
* years 39 to 99 are assumed 1900's and years 0 through 38 are 2000's.

Pass 2.5
If we encounter a d:d:d or d:d structure, treat it as h:m:s or h:m and update the HOUR, MINUTE and SECONDS variables.
If we encounter "pm" or "PM" (but no periods) then add 12 to the HOUR variable if it's less-than 12.
* (am and AM are just ignored)

Pass 3
If we encounter the first 3 letters of a month, ignore the rest of the spelling and update our MONTH variable.


Random words that aren't touching are ignored. Day-Of-Week are ignored. "am" and "AM" are ignored in Pass 2.
The ordinal suffixes "st", "nd", "rd", "th" that are touching a 1 to 2 digit number are stripped and ignored in Pass 1.
Zero padding is stripped and ignored. Any number anywhere can be ridiculously zero-padded.
xxx However, any other random characters that prefix or suffix a number will invalidate the function.
/* This should probably be fixed --- that would solve a host a formatting issues, like comma usage.
You could strip and ignore random suffixing characters like you do with ordinals st nd rd th. */

Example: 02 1/1/1 Feb 01:23 Apricot 2019 pm
Result: Sun Apr 01 13:23:00 2001

Is that correct?
Posted By: Khaled

Re: $ctime(string) eval - 12/11/19 10:24 PM

That looks about right.

That said, I am not going to write all of that in the help file.

The purpose of the help file is to give an overall description of how a feature works, with some examples, not to provide pseudo-code that mirrors every possible if statement, exception, etc. in the actual code.

In fact, I wouldn't depend on the above pseudo-code at all, because I might change the code completely in the future.
Posted By: Protopia

Re: $ctime(string) eval - 12/11/19 10:52 PM

I agree with Khaled's philosophy here - the Help file should not document every quirk - that is what forums are for.

But please feel free to add the psuedo-code to the WikiChip page https://en.wikichip.org/wiki/mirc/identifiers/$ctime
Posted By: Raccoon

Re: $ctime(string) eval - 14/11/19 12:13 AM

Honestly, I wasn't even asking about the help file. I don't really care about the help file. Not saying that it couldn't use some more information, but that's not why I came here. My elaboration was strictly so I could analyze the mechanics of how $ctime() works in order to become a better beta tester.

Though feel free to borrow from this.

Returns the number of seconds elapsed since 00:00:00 GMT, January 1, 1970 based on the date that you specify.
Accepts any date format that contains "Jan" to "Dec" for month, numbers 1 to 31 for day, numbers 32 to 99 or 1601 to 9999 for year, or the shorthand d/m/y, y/m/d, d-m-y, and y-m-d. But not m/d/y or m-d-y. Optionally, may also include the time of day in h:m or h:m:s as 12h or 24h format.

$ctime(January 1 1970 00:00:00)
$ctime(3rd August 1987 3:46pm)
$ctime(21/4/72 1:30:37)
$ctime(Wed 1998-3-27 21:16)
Posted By: Protopia

Re: $ctime(string) eval - 14/11/19 08:10 AM

Ah - now if we are talking about testing...

What we really need is a community effort to build a comprehensive regression test script (on GitHub perhaps) that tries to test as many variants of each element of mSL as it can.
© 2019 mIRC Discussion Forums