mIRC Home    About    Download    Register    News    Help

Print Thread
Page 1 of 2 1 2
#265145 12/03/19 11:01 PM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
$gmt(number) works for returning the current timestring, but not when number is a time in the opposite $daylight condition compared to now().

As I understand the time rules, GMT/UTC never goes to daylight time, so the $gmt() datestring for a specific number should always be the same $gmt string regardless of whether daylight time was inside/outside daylight time for either now or the target time:

Code:
//var %a 1547056800 | echo -a asctime: $asctime(%a) vs gmt: $gmt(%a)


With pc time set to USA Central timezone, when the date is during daylight time, this is now showing a 5 hours difference:

asctime: Wed Jan 09 12:00:00 2019 vs gmt: Wed Jan 09 17:00:00 2019

However if I set my pc time to a January date, the $gmt string for the same number changes by 1 hour without shifting the $asctime string:

asctime: Wed Jan 09 12:00:00 2019 vs gmt: Wed Jan 09 18:00:00 2019

Instead of returning the GMT, this appears to returns a time that's simply the $asctime shifted by the current $timezone value, regardless whether the parameter is for a date falling during the opposite daylight daylight condition. $timezone has always changed value depending on whether the current time is during/outside daylight time, where $timezone + $daylight is always the same total, so perhaps the current $timezone value is being applied to all $gmt(number) values throughout the year.

-

This shows the transition date where USA recently went to daylight time:

Code:
//var -s %time $ctime( 2019-03-09 12:00:00) , %i 0 | while (%i isnum 0-24) { var %a $calc(%time + 3600* %i) | echo -a asctime: $asctime(%a) vs gmt: $gmt(%a) | inc %i }



When the clock is set to a January date, the displayed $asctime vs $gmt times begins as 6 hours apart, and for a few hours during the transition they differ by 7 hours, then resumes being 6 hours apart. When the clock is set back to March, the times instead begin as 5 hours apart, then differ by 6 hrs for a few hours, then resume being 5 hours apart. This makes it difficult to get an accurate $gmt(number) string for a distant date without being able to calculate whether $daylight was 0 or 3600 at that point in time.

There should be no 1-hour GMT jump because it never goes on/off GMT.

Another way to describe the issue is that when the target date is in the opposite daylight condition from the current time, shifting by an exact multiple of 86400 seconds should have the $asctime string be shifted by 1 hour, but the $gmt string should not, but it does:

Code:
//var %a $ctime , %b $calc(%a - 59*86400) | echo -a asctime: $asctime(%a) vs $asctime(%b) gmt: $gmt(%a) vs $gmt(%b)



If fixing this breaks backwards compatibility for something, perhaps there can be a new $utc() identifier.

maroon #265216 19/03/19 11:41 AM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Quote:
Instead of returning the GMT, this appears to returns a time that's simply the $asctime shifted by the current $timezone value, regardless whether the parameter is for a date falling during the opposite daylight daylight condition. $timezone has always changed value depending on whether the current time is during/outside daylight time, where $timezone + $daylight is always the same total, so perhaps the current $timezone value is being applied to all $gmt(number) values throughout the year.

That is exactly what is happening.

When $gmt() was added (v5.51, item 43), its purpose was to support $gmt(format), not $gmt(N). It should have returned an error with N but it didn't. Some scripters started using $gmt(N) and, over time, requested that N be interpreted differently, so it was changed a few times.

If you test this with mIRC v6.35, does it return the value you are expecting?

Khaled #265219 19/03/19 03:53 PM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Yes, v6.35 returns the expected $gmt times. The 1st example showed the GMT time-string ending with 18:00:00 regardless whether the pc clock is Jan 19 or Apr 19. Neither of these calendar dates shows the GMT jumping by an extra hour on the transition date to/from daylight mode, though the rules were different back then, so the command needed to edit the date to either 2018-10-27 12:00:00 or 2019-04-06 12:00:00 instead, which both make that snippet show the $asctime(N) changing by 2 or 0 hours at 2am but the $gmt(N) doesn't.

And this revised snippet shows any dates within +/- 183 days of today, by adding or subtracting a multiple of 86400 seconds. It displays any date where the GMT time-of-day differs from the current time. For both Jan19/Apr19, in v6.35 it correctly shows no dates, but in 7.55 it shows every date in the opposite daylight-state compared to the date the pc clock is set to.

Code:
//var %a $ctime , %i -183 , %gmtnow $gettok($gmt(%a),4,32)  | while (%i < 183) { var %gmt $gmt($calc(%a + 86400*%i)) | if ($gettok(%gmt,4,32) != %gmtnow) echo -a %i : %gmt vs %gmtnow | inc %i }



I tested Apr19 in case there was a side-effect from v6.35 seeing the daylight rules differently than they really are. When setting the pc clock to a date between the new/old transition dates, including today, v6.35 reports $asctime($ctime) as being 1 hour ago.

maroon #265223 19/03/19 08:21 PM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Quote:
Yes, v6.35 returns the expected $gmt times.

You have included a number of observations after the above sentence... I am going to assume that they illustrate that $gmt(N) in v6.35 is fully working the way you expect.

So, if v6.35 is working the way you expect, it looks like a previous scripter was trying to do something with $gmt(N) that was not giving the result they expected and requested that it be changed to the current behaviour. Considering that $gmt(N) is not documented, that seems fair enough.

Unfortunately, the scripter may no longer be around, so there's no way to know why they requested this.

In this case, the old code from v6.35 is actually still there, just commented out, so I could change it back. But... can you think of a reason why the current behaviour would make sense?

Khaled #265227 20/03/19 03:58 AM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
I can't think of any reason why someone would need $gmt(N) to be applying the current $daylight's offset to times across the entire year. Based on the thread I quote below, I suspect the reasons for changing had to do with the changed on/off times for daylight time, and not from using N against a date 6 months away from the current date.

The only change I've identified that should change would be preventing $gmt(N) from reporting times as if GMT goes on/off daylight time, preventing $gmt(N) from applying the current daylight rules across the entire year. The fix would also allow $gmt(0) to be midnight all year long, instead of reporting during summertime as if it were 11pm Dec 31st.

The parts of the v6.35 behavior I would warn about would be:

#1. applying the effect of the old on/off daylight rules
#2. applying the effect of the old definition of $timezone.

Quote:
Considering that $gmt(N) is not documented, that seems fair enough.


Actually, $gmt(N) is sorta documented. The documentation is easy to read as if there's support for $gmt(N). Near the top of "/help Time and Date Identifiers" is:

Quote:
"The identifiers $time(), $date(), and $gmt() can also be used with the format specification below."


This was within the section for $asctime, where it shows 3 kinds of syntax, where 2 of the 3 use the N parameter, so myself and everyone else I've spoken with reads this as applying all 3 kinds of syntax to $gmt and the others.

I tested v7.36 and found the current behavior, so I'm assuming the $gmt behavior changed due to the v7.05 item in versions.txt:

Quote:
7.Fixed $gmt and other time-related identifiers to correctly include timezone and daylight offsets.


If so, this thread from a couple months prior to that release is possibly related to this $gmt issue:
https://forums.mirc.com/ubbthreads.php/topics/211013/Re:_$gmt_returning_incorrect_v#Post211013

(#1)

If the changes were made based on that thread, I suspect that the issues they were reporting were caused by the switch in daylight rules. That thread is from 2010 where the new rules had the daylight transition at 2am Sunday March 8th, but v6.35 was hard-coded using the old rules where the transition wasn't scheduled until 2am Sunday April 5th. These posts were in late March of that year, so there were some kinds of 'wrong' results during the 4 weeks between those dates.

In 2019, v6.35 will continue returning the wrong spread between $asctime(N) vs $gmt(N) until this coming Sunday April 7th at 2am. As I mentioned in the prior post, v6.35 within USA timezones will make $asctime($ctime) display the wrong time for the next few weeks, and the workaround for programs using the wrong timezone rules would be to change the clock to use a timezone from 1 hour later which doesn't use daylight rules. i.e. UTC-5 Bogota for USA UTC-6 Central, or UTC-4 Georgetown for USA UTC-5 Eastern.

(#2)

Something else to watch out for is how v6.35 has a different definition of $timezone compared to versions since then. For v6.35, $timezone is a constant number all year long, including the months where $daylight changes from 0 to 3600. However, currently the $timezone value changes so the combined total of $calc($timezone + $daylight) is a constant total, regardless of the $daylight value. For USA Central, $timezone is 21600 during the winter, but changes to be 18000 during summertime. But the combined total of $daylight + $timezone remains 21600 all year long.

Hopefully fixes to $gmt wouldn't cause a whack-a-mole problem with scripts who've become accustomed to the new $timezone definition.

maroon #265230 20/03/19 01:40 PM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Right, I see what is happening.

Support was added only for $gmt(format). When the changes where made to $gmt() in 2010, they applied specifically to $gmt(format), which assumes N is $gmt.

$gmt(N) is simply not catered for, and has never been catered for, in any way. It only returns a value because an error is not being reported. The scripter who requested $gmt(format) wanted just that - an easy way of formatting $gmt.

So, to cater for $gmt(N), what would you like me to assume that N represents? Would you like the N value to be passed to localtime(), gmtime(), offset by timezone and daylight savings? etc.

Khaled #265232 20/03/19 08:51 PM
Joined: Feb 2003
Posts: 2,812
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
I think the simple rule should be thusly:

$gmt(0) == Thu Jan 01 00:00:00 1970
$gmt(3600) == Thu Jan 01 01:00:00 1970
$gmt(-3600) == Wed Dec 31 23:00:00 1969

Currently these values are incorrectly-offset by one hour if your local-time is in DST. $gmt() should be local-time-DST agnostic.

GMT does not observe DST, same as UTC. For all intents and purposes, mIRC should treat GMT and UTC as the same thing, even though UTC has some silly leap-second rule differences.


Well. At least I won lunch.
Good philosophy, see good in bad, I like!
Raccoon #265233 20/03/19 10:55 PM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Agreed.

//gmtcalc $calc( 1547987696 + 86400*0)
//gmtcalc $calc( 1547987696 + 86400*181)

The first number displayed is calculating the gmt(N)'s time of day using % mod and // floor divide, and always shows 12:34:56, regardless of the time of year, and that's what $gmt(N) should do.

Instead, when the clock is set to January, $gmt(N) shows them as:

Sun Jan 20 12:34:56 2019
Sun Jul 20 13:34:56 2019

But using the same pair of $gmt(N)s during July shows the date strings as:

Sun Jan 20 11:34:56 2019
Sun Jul 20 12:34:56 2019

$gmt should not be leaping forward in the spring then falling back in the fall, and should always show the same time for the same N.

Code:
alias gmtcalc {
  var %gmt $$1
  var %day $calc(%gmt // 86400)
  var %tmp $calc(%gmt % 86400)
  var %hours $calc(%tmp // 3600)
  var %mins $calc((%tmp - (%hours * 3600)) // 60 )
  var %secs $calc(%tmp % 60)
  echo -a days %day $+(%hours,:,%mins,:,%secs) vs $gmt($1)
}

maroon #265234 21/03/19 10:03 AM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Alas, there is no point in referring to the current results from $gmt(N). $gmt(N) is not catered for in any way in all previous versions of mIRC. It should have returned an error.

If I understand correctly, what you are requesting is for $gmt(N) to return the same result as $asctime(N). This will be in the next version.

mIRC uses CRT time functions in hundreds of routines to perform time calculations. These functions cannot handle anything before unix epoch.

Khaled #265235 21/03/19 04:41 PM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
No, unless the computer's time settings were changed to use as the timezone "UTC" or "Reykjavik", where the offset from UTC is zero year round, and there's no daylight saving time period. As Raccoon was saying, $gmt(N) for a specific N should return the same as UTC(N), a time not offset by daylight, and not messing around with leap seconds.

$gmt(0) should report the same thing for everyone, as it currently does. But it also should report the same thing all year long, instead of adjusting its results based on the current value of $daylight.

For USA Central, $asctime(0) reports "Wed Dec 31 18:00:00 1969", and a different time for everyone in a different timezone. $gmt(0) for everyone should be "Thu Jan 01 00:00:00 1970"

As my alias in the prior post was showing, when "N" is a multiple of 86400 it should return midnite. Any modulo is the hr:min:secs since midnight.

In effect, the HH:nn:ss portion of the display should be the same as

//echo -a $duration( $calc(N % 86400) ,3)

And makes most of the alias in the prior example simpler:

//echo -a $duration( $calc($calc($calc( 1547987696 + 86400*181)) % 86400) ,3)
//echo -a $duration( $calc($calc($calc( 1547987696 + 86400*0 )) % 86400) ,3)

result: 12:34:56

maroon #265236 21/03/19 06:41 PM
Joined: Feb 2003
Posts: 2,812
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
Khaled: It's a simple DST bug with $gmt that should be possible to correct.

Desired output, all the time any time:

$gmt(0) == Thu Jan 01 00:00:00 1970

During the summer months, during local DST, these outputs are violated and unreasonably change.

$gmt(0) == Wed Dec 31 23:00:00 1969 (wrong)

$gmt() should be local-time-DST agnostic. Epoch happened Jan 1 1970 at midnight.


Well. At least I won lunch.
Good philosophy, see good in bad, I like!
Raccoon #265237 21/03/19 06:45 PM
Joined: Feb 2003
Posts: 2,812
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
$gmt(n) is a useful function. I've been using it to display the UTC date & time of a UNIXTIME value for years. People prefer and expect UTC time from IRC bots.


Well. At least I won lunch.
Good philosophy, see good in bad, I like!
Raccoon #265245 22/03/19 09:33 AM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Quote:
$gmt(n) is a useful function. I've been using it to display the UTC date & time of a UNIXTIME value for years. People prefer and expect UTC time from IRC bots.

I am sorry to say that it has just been luck that it returned a reasonable value. The routine used by $gmt() is used by other identifers and it just happens that the N value it used pre/post v7.10 is what it is, not to mention which of two CRT time functions that it was passed to.

maroon #265246 22/03/19 12:05 PM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Quote:
I can't think of any reason why someone would need $gmt(N) to be applying the current $daylight's offset to times across the entire year. Based on the thread I quote below, I suspect the reasons for changing had to do with the changed on/off times for daylight time, and not from using N against a date 6 months away from the current date.

Very well, I am going to change $gmt() back to its v6.35 incarnation. This will affect the results of $gmt(N) and $gmt(format).

Khaled #265255 23/03/19 09:36 AM
Joined: Feb 2003
Posts: 2,812
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
Is there a format that I could/should be using to determine the UTC date-time string of any historical UNIXTIME value?

I'm thinking something like $asctime($calc(%unixtime - $timezone + $daylight)) but I can't seem to get the logic right to work in both Summer and in Winter.

I would also like to report a pseudo-bug in $asctime() in that it will not support negative UNIXTIME values. (although $gmt(n) does support negative unixtime values). ((why would I want $asctime to support negative values? so I can adjust for $timezone when passing 0 (zero) epoch time, and get Jan 1 1970 result. And so I can get results for somebody's birthday if they're born prior to epoch. ie, if they just turned 65, I can subtract 60*60*24*365.25*65 from $ctime and get the day of week they were born on)).


Well. At least I won lunch.
Good philosophy, see good in bad, I like!
Raccoon #265257 23/03/19 10:40 AM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Quote:
I would also like to report a pseudo-bug in $asctime() in that it will not support negative UNIXTIME values.

None of the CRT time functions support negative values. Actually, that's not entirely true. They will apply timezone/dst adjustments to the value provided, so can handle negative values up to a certain point. However, the results will be wrong. In addition, the CRT time functions crash (or at least, they used to) if provided with an invalid range, so applications have to detect that.

Raccoon #265267 24/03/19 02:38 PM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
The latest beta should now be returning the expected $gmt(N) and $gmt(format) results. If it isn't, please let me know. That said, I have found an issue with z/zz/zzz being offset by DST incorrectly, which has been fixed for the next version.

Regarding negative time values prior to unix epoch: I have implemented some drop-in replacements for the CRT time functions that use the Windows API time functions. These can handle dates from Windows epoch 1 January 1601. These seem to be working. That said, it took a long time for the current date/time identifiers to stabilize due to the quirks in the CRT/API functions in different versions of Windows. I will be creating a /command that allows you to toggle whether mIRC uses the drop-ins or not, for testing purposes. This should be in the next version.

Raccoon #265284 26/03/19 07:16 PM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
The latest beta now implements a number of fixes relating to timezone/DST.

It also includes support for using Windows API time functions as opposed to CRT time functions.

The results for the APIs may vary across Windows versions as mIRC uses GetDynamicTimeZoneInformation() from Vista onwards, and GetTimeZoneInformation() for older versions of Windows. There are other APIs for improved DST/timezone support, including historical changes, but it all gets very convoluted.

The API support can be enabled using /timeapi on|off to allow you to compare results between API and CRT calls. This setting affects all features that use times/dates, not just identifiers.

The API versions also support negative pre-unix epoch time values from year 1601 onwards.

This beta is also using thread-safe versions of the CRT functions.

The API support needs heavy testing. If it looks like it is working correctly under different versions of Windows/WINE/etc., it will be permanently enabled. On the other hand, if it looks like it is causing more issues than it resolves, the changes will be reverted.

Khaled #265285 26/03/19 07:49 PM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Win7-32

I'm seeing $asctime timestamp shifting by 1 hour when N is in the opposite daylight zone than the current day.

//var %a $calc($ctime - 90*86400) | timeapi on | echo -a $asctime(%a) and $asctime(0) | timeapi off | echo -a $asctime(%a) and $asctime(0)

$ctime(date string) also interprets time differently by 1 hour if the date is in the opposite daylight setting:

//var %a $asctime $calc($ctime - 90*86400) | timeapi on | echo -a $ctime(%a) | timeapi off | echo -a $ctime(%a)

Edit: another example of something that should return back to the original time, and it does with timeapi off, but with /timeapi on, it goes back in time 10 hours, which i assume is due to my timezone's local time adjusted for daylight is GMT-5

//timeapi on | var -s %a $asctime , %b $ctime(%a) , %c $asctime(%b)



Last edited by maroon; 27/03/19 01:13 AM.
maroon #265286 27/03/19 07:35 AM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Quote:
I'm seeing $asctime timestamp shifting by 1 hour when N is in the opposite daylight zone than the current day.

$asctime() returns N in local time. It passes the N time value directly to the localtime() function which calculates the result. Do you have any experience with the localtime() time function? If you do, would you know how you would call it in order to return the result you are expecting for $asctime()?

maroon #265289 27/03/19 03:29 PM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Quote:
Edit: another example of something that should return back to the original time, and it does with timeapi off, but with /timeapi on, it goes back in time 10 hours, which i assume is due to my timezone's local time adjusted for daylight is GMT-5

Ack. This was harder to track down than I expected. There are quite a few API calls involved in converting between unix/system/file times, some of which apply offsets themselves, and the drop-ins can call each other in some cases. This issue has hopefully been fixed for the next version.

Khaled #265290 27/03/19 04:19 PM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Nope, don't have experience with it. When you say "you are expecting", are you implying that I'm expecting something I shouldn't? If your effective timezone right now is GMT+0 you won't see the entire effect I'm seeing. And someone else tested XP and saw the same effects I was describing earlier, except it was doubling their GMT offset instead of mine.

//var -s %a Jan 01 12:00:00 2019 | timeapi off | var %aoff $ctime(%a) | timeapi on | var %aon $ctime(%a) | echo -a $calc(%aon - %aoff ) | var -s %a Jun 01 12:00:00 2019 | timeapi off | var %aoff $ctime(%a) | timeapi on | var %aon $ctime(%a) | echo -a $calc(%aon - %aoff )

There 2 effects going on, and I'm not sure that $asctime can be blamed for both. The 1 hour offset seems to be a problem in $asctime(N) where it never transitions on/off daylight time. However the above code doesn't use $asctime at all, and it's showing a 1 hour effect.

When clock is set to USA Central with the current date during daylight time, the GMT offset is -5. The above snippet shows -39600 then -36000, or -11 hrs and -10 hrs. When clock is set backwards 1 month to be in standard time where GMT offset is -6, the results are -43200 then -39600, or -12hrs and -11hrs.

So it looks like there's a 1 hour issue in both $asctime and $ctime, as well as a doubling of the GMT offset for $ctime(string)

maroon #265297 28/03/19 11:53 AM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Quote:
Nope, don't have experience with it. When you say "you are expecting", are you implying that I'm expecting something I shouldn't?

I was hoping you would know what I'd need to do in this case to return the result that you think is right. At this point, I am not convinced I know enough about this subject to be sure.

After spending the last week reading about timezones and DST, I have come away thinking that its not as simple as it sounds, eg. deciding between prior or subsequent DST states at DST transition points, historical DST, dynamic DST, matching ISO timezone/DST rules, updating to the latest rules, CRT functions not supporting the latest changes (currently using Visual Studio 2008), Windows APIs not supporting these except in recent versions, libraries specifically written to handle timezone/DST not working correctly, leap seconds only applying prior to 1970 (although Windows 10 now includes them in API results), and so on.

Regarding /timeapi on|off: I thought this would be useful to allow comparisons between the CRT and API results. However, as the APIs are more up-to-date, the results may actually differ, not to mention that they may return different results on different versions of Windows.

That said, the new API implementation does have several bugs and I have implemented fixes in the next version, so we will have to see how that turns out.

Khaled #265308 29/03/19 07:53 PM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Can you confirm beta 907 is using the new API? I can't find any differences in $asctime compared to no-beta, but /timeapi no longer reports any messages to indicate if it's switching the API on/off.

What makes it look like the new API isn't enabled is that the no-differences also includes reverting to the old behavior of $asctime(N) not recognizing negative numbers or $ctime(string) not recognizing dates prior to 1970.

maroon #265309 29/03/19 08:37 PM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Originally Posted By: maroon
Can you confirm beta 907 is using the new API? I can't find any differences in $asctime compared to no-beta, but /timeapi no longer reports any messages to indicate if it's switching the API on/off.

The /timeapi command is showing the on/off message here for me with beta 907.

Khaled #265310 29/03/19 09:37 PM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
sorry. i got bit by an alias i was trying to use that could run the timeapi in both beta and nobeta.

I'm not yet seeing any issues with $asctime, but $ctime is translating date strings in the opposite daylight zone to a different N than before, which results in a 1 hour earlier difference when translating a january timestring to N, then using asctime back to timestring:

//var -s %a $ctime(jan 29 12:34:56 2019) , %b $asctime(%a)

In nobeta this returns to 12:34:45, but in 907 it displays 1 hour earlier at 11:34:56

The difference is in the N created by $ctime(string) not in the string returned by $asctime(N)

Nobeta reported $ctime(Jan 01 00:00:00 1970) as 21600, reflecting the wintertime GMT-6 offset of USA Central's standard time. 907 reports it as 18000 reflecting the current date's GMT-5 daylight offset.

The difference localizes to the hour when time transitions between daylight and standard time. The following reports 3600 in nobeta, but 7200 in 907:

//var -s %a $ctime(mar 10 03:00:00 2019) , %b $ctime(mar 10 01:00:00 2019) , %c %a - %b

I got mirc to crash while testing negative dates, so trying to localize where the culprit lies.

maroon #265311 29/03/19 09:45 PM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Just to confirm: do you mean that these issues are happening with /timeapi on or off or both?

Khaled #265312 29/03/19 09:48 PM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
sorry for not being clear. the most recent report was with /timeapi ON

my prior statements about not finding any differences vs nobeta was because that alias had me frozen in OFF mode.

maroon #265313 30/03/19 04:59 AM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
update:
looks like the beta 907 crash was due to $asctime(N) using N which is either too large positive or too large negative. I had used a loop where I had assumed an echo error would break out of the loop when $asctime(N) returned $null for being out of range. But instead it crashed when N went too far below range.

For negatives, as it continues further away from zero, it continues displaying time string Jan 01 1601 00:00:00 for a large range of negatives below the N belonging to that time string. However, it crashed when the N became too far below zero. The next line displayed for me, but changing -29228 to 29229 generated a crash.

//var -s %a $calc(-11644452000+365.2425*86400* -29228) | echo -a $asctime( %a )

For large positives, the new API supports years up through 9999, but crashes for any timestring displaying later than Dec 31 9999 23:59:59, so crashing the next command would require changing "*0" to another integer which would depend on the timezone.

//var -s %a $calc(253402300800+3600*0 ) | echo -a $asctime( %a )

maroon #265314 30/03/19 10:36 AM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Quote:
looks like the beta 907 crash was due to $asctime(N) using N which is either too large positive or too large negative.

Thanks, I was able to reproduce this. This is due to the strftime() function in the CRT which needs to be used even with "/timeapi on" because there is no API replacement for it. Unfortunately, it has the same issue as other CRT functions; it performs invalid parameter checks and terminates an application if parameters aren't within the range it expects, instead of just returning an error to the caller.

One solution would be to disable invalid parameter asserts in the CRT using _set_invalid_parameter_handler(). But this would affect all CRT function calls in the release version. On the one hand, this would prevent mIRC from crashing in such situations. On the other hand, we wouldn't know that there was an error.

That said, I am only able to get it to crash if the time value is beyond year 9999. If the time value is below year 1601, no crash occurs here; localtime() adjusts the time value to a minimum of 1601. So even with the invalid parameter handler, it would not be possible to detect if a date less than 1601 was supplied.

So the only way to prevent/detect errors with strftime() seems to be check if the tm structure being passed to strftime() contains a date range close to the minimum 1601/maximum 9999 dates and, if so, to not call strftime(). Not a great solution but I can't think of any other options at this point. This will be in the next version.

maroon #265315 30/03/19 12:02 PM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Quote:
$ctime is translating date strings in the opposite daylight zone to a different N than before

Okay, I think we're getting there :-) Added another check to my unit test. Fixed in the next version.

Khaled #265328 02/04/19 07:52 AM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Doesn't crash now for high or low date values, and I'm not seeing any of my examples above messing up. All examples assume: /!timeapi on

Highest value it now displays is 2 seconds before midnite at the end of year 9999.

//var -s %a $calc(253402300800+3600*05+3598 ) | echo -a $asctime( %a )

(The 05 depends on the timezone offset from GMT, and so will the 06 number below)

Lowest displayed value is 1 second after midnite 1/1/1601

//var -s %a $calc(-11644473600+3600*06+1) | echo -a $asctime( %a )

While there aren't any out of range crashes, there is a recurring pattern of wildly invalid N's which are returning not-null strings as if they're within range:

//var %i -500000 | while (%i < 500000) { var %a $calc(-11644452000+365.2425*86400* %i) , %time $asctime(%a) | if (%time) echo -a %i $asctime( %a ) | inc %i }

maroon #265329 02/04/19 09:33 AM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Thanks for testing it out.

Quote:
While there aren't any out of range crashes, there is a recurring pattern of wildly invalid N's which are returning not-null strings as if they're within range:

Overflow due to conversions in various Windows APIs. I could add a range check in $asctime() to prevent it from returning a result in the above example. That said, you can reproduce similar overflow issues in pretty much every identifier.

Khaled #265369 05/04/19 11:08 PM
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
The overflows are gone in beta 1211.

Just an observation that, while the new API expanded the range for $asctime(N) from the 2nd second of 1601 thru the last second of 9999, the range for $ctime(date-string) remains the same. For me, valid limits are:

//!timeapi on | var -s %hi_valid $ctime(Jan 01 01:59:59 3001) , %low_valid $ctime(Jan 01 00:00:00 1970)

//!timeapi on | var -s %hi_invalid $ctime(Jan 01 02:00:00 3001) , %low_invalid $ctime(Dec 31 23:59:59 1969)

I'm guessing the higest valid ctime(date) conversion depends on your offset from USA Pacific.

maroon #265371 07/04/19 09:25 PM
Joined: Dec 2002
Posts: 5,412
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,412
Thanks, this should be fixed in the next beta.

Page 1 of 2 1 2

Link Copied to Clipboard