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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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()?

Page 1 of 2 1 2

Link Copied to Clipboard