Additional packages to use with NodaTime - nodatime

I am updating an application to use NodaTime to fix many existing time issues with our data and processes.
I will need to resolve timezones from a mobile app that sends IANA timezone names. I will need to support conversions to UTC using custom offsets (i.e. hard coded -04:00). I may or may not need to support Windows timezone names as well.
For all of this, I am wondering if I need additional packages. How do TimeZoneConverter and TimeZoneNames work alongside NodaTime? Are there any other additional packages I should use alongside NodaTime?
Our ultimate goal is to get all data persisted as Utc and convert to/from user time only for display or accepting user input.

You don't need any extra packages for that scenario, as far as I can see.
For IANA IDs, just use DateTimeZoneProviders.Tzdb
For "raw offset" IDs, you can use any time zone provider, asking for an ID of the form "UTC+01:00" etc. (So you'd need to add the "UTC" prefix.)
For Windows zone mapping, you can use TzdbDateTimeZoneSource.Default to get the default TZDB information, then use the WindowsMapping property to get a WindowsZones object you can use for mapping.
TimeZoneConverter may well be simpler to use for the last bullet point, but it's not required. The IANA IDs it provides should work fine with Noda Time.
TimeZoneNames is more about displaying time zone names to users. If you don't need to do that, you probably don't need the package.
Note that persisting all data as UTC may be a really bad idea - it's hard to tell without knowing more about your application. If you only deal with values in the past, or if they're fixed instants in time, that's fine. But if you're allowing users to schedule future events, I'd store the values that the user gave you. Here's an example of why...
Suppose the user says they want to schedule an event for Europe/Paris at 9am on December 1st 2021. If you convert that to UTC now, you'll end up with 2021-12-01T08:00Z, because the current time zone rules say that Paris will be at UTC+1 in December 2021.
However, it's entirely possible that between now and 2021, France will have changed its time zone rules to be on "permanent daylight time", i.e. UTC+2 all year round. At that point, your UTC value of 2021-12-01T08:00Z would correspond to 10am in Paris on the given date - contrary to what the user specified.
It's fine to convert to UTC as well so that you can create a totally ordered view of the data, so long as you retain enough information to perform that conversion again every time there's new time zone data.
As I say, that may not be an issue for you, but it's worth knowing that the "received wisdom" of "Always store everything in UTC" is really not good advice for all scenarios.

Related

Is there the way to parse time with timezone in Qt?

I need to parse strings with time like '09:21:15 EST' (where EST is US Eastern timezone), so that the information about summer / winter time (daylight saving time) is correct, so that UTC−05:00 is used for winter dates, and UTC−04:00 for summer dates.
It is also necessary to support the direct setting of the UTC offset - '09:21:15 UTC−04:00', in which case daylight saving time should not be taken.
I Didn't find anything intelligible and sensible in Qt documentation for QDateTime, QDate, QTime, QTimeZone etc.
Is there an easy way to solve this problem?
In general, in any language, what you ask cannot be done reliably.
EST is not a time zone. It's an English abbreviation for an aspect of a time zone.
There are places that use EST without EDT, such as Jamaica for example. See more here.
There are non-English abbreviations to consider, such as HNE that's used in places in French-speaking Canada such as Montréal.
Many abbreviations are ambiguous. For example CST could be Central Standard Time, Cuba Standard Time, or China Standard Time.
Many time zones don't have any abbreviation - even in English. They are sometimes given invented (made up, artificial) abbreviations that aren't legal or in common usage, but in reality they are referred to by their country name or only by their UTC offset (for a given timestamp).
In order to convert between time zones reliably for multiple timestamps, you need an IANA time zone identifier, such as "America/New_York". QTimeZone can work with these.
On any given timestamp you can have an offset from UTC, such as -05:00. You can set an offset when using QDateTime.
If you are absolutely sure you are only working with timestamps from North America containing common English abbreviations, you could build and use an opinionated mapping between string and offset, such as "EST" == -5, "EDT" == -4, "CST" == -6, "CDT" == -5, etc. But it can only map abbreviation to offset, not to a time zone. (See also "Time Zone != Offset" in the timezone tag wiki.)
Qt likely has the features you need already implemented.
With QDateTime::fromString you can use t in the format string to mark timezone characters.
Have a look into this question as well: Qt QDateTime from string with timezone and daylight saving
There you can get an example, which shows that you need the QDateTime in the LocalTime specification to be able to deal with daylight saving times.
However, QDateTime::offsetFromUtc is dependent from the QDateTime's current specification...
I guess, you would need to always convert the QDateTime object to the same TimeSpec before comparing offsetFromUtc

Calculate datetime between client and server (Node JS)

I have an application that uses subscriptions for each member that joins. I'm having some issues with dates and calculations related with it. For example, let say a member joins on 2/10/2020 at 10:00. When the user submit the request to the server to process the subscription (the server is using UTC) the date that is being calculate is 2/10/2020 16:00 (because I'm -6:00 hours from UTC). This scenario is OK at this point, because the date is still the same (no matter the time). But, if we replicate this scenario when the user joins for example 2/10/2020 at 19:00, when the request is received and calculate the date, the result is 2/11/2020 01:00, and that produces an error in the invoice because the billing date of the invoice is wrong (one day after). What is the best way to implement this? I have read a lot of this topic, but most of the pages and questions are related in the other way, server to client, to parse of format dates to display to the user.
I have several questions related with this process.
Should I sent the date for the UI to the API? Or the timezone and
based on that, calculate the date in the API? (since the server have
UTC)
Moment.js library have a way to solve this or should be better with vanilla Javascript using Date?
Is there any HTTP header for the request to handle the time or date?
This really depends on what behavior you want to have. Before you try to fix anything, think through and decide on the exact requirements for what the billing date should be based on.
Is the user's time zone relevant? If so, you'll likely need to know what the user's time zone is. You'll be potentially assigning different dates to different invoices even if they're using the same UTC point in time. Your business might get confused on why some customers have invoice dates before or after the business day.
Or maybe the time zone of your company is more relevant? Many business work that way. All of your invoices will be aligned, but some customers might get confused on why their invoice date is before or after their current date.
Or maybe some customers snap to time zones of nearby offices, in the case of businesses with offices around the world.
Only you and your company can decide this. There are probably other options I'm not thinking through here. It's a business decision, not a technical one.
On your three questions:
That depends on what you decide above.
Libraries are a good idea for simplifying your code, but they're not a hard requirement. You can use the Date API, if you know what you're doing, but you may find libraries easier to work with. Also, Moment is in maintainance mode. For new development, the Moment team recommends you use Luxon instead of Moment. There are other popular modern libraries also, including date-fns and js-Joda.
There's the date header, but that's not going to help you with this.

NodaTime TimeZone Data files naming

It appears that the time zone database files used by Nodatime are named by year, with releases within the same year incrementing by a
letter - i.e., "tzdb2019a.nzd" is current as I write this, the next release
will be "tzdb2019b.nzd", and some of the previous versions may have been
"tzdb2018a.nzd", "tzdb2018b.nzd", "tzdb2018c.nzd", etc.
However, I have not been able to find this naming convention formally documented anywhere, and assumptions make me nervous.
I expect the time zone data to change more often than my application
is updated, so the application periodically checks for the latest data file at
https://nodatime.org/tzdb/latest.txt, and downloads a new file if the one in
use is different. Eventually there will be several files locally available.
I want to know that I can sort these by name and be assured that I can
identify the most recent from among those that have already been
downloaded.
That's what I anticipate, certainly. We use the versioning from the IANA time zone page, just with a tzdb prefix and a .nzd suffix. So far, that's been enough, and it has maintained the sort order.
It's possible that we might want to provide other files at some point, e.g. if there's no IANA changes for a long time (as if!) but the CLDR Windows mapping files change significantly. I don't have any concrete plans for what I'd do in that case, but I can imagine something like tzdb2019-2.nzd etc.
It's hard to suggest specific mitigations against this without knowing the exact reason for providing other files, but you could potentially only download files if they match a regex of tzdb\d{4}[a-z]+.nzd.
I'd certainly communicate on the Noda Time discussion group before doing anything like this, so if you subscribe there you should get advance warning.
Another nasty possibility that we might need more than 26 releases in a single calendar year... IANA says that would go 2020a...2020z, then 2020za...2020zz etc. The above regex handles that situation, and it stays sortable in the normal way.
Another option I could provide is an XML or JSON format for "all releases" - so just like there's https://nodatime.org/tzdb/index.txt that just lists the files, I could provide https://nodatime.org/tzdb/index.json that lists the files and release dates. If you kept hold of that file along with the data, you'd always have more information. Let me know if that's of interest to you and I'll look into implementing it.

How to code - 'Date' comparison in Alloy?

I'm a beginner in Alloy. This is my first model using Alloy Analyzer. I'm now building a generic model for Travel in Alloy. In this model, a user (I use sig Request in this model) can make a request for 'accommodation' (includes 'hotel' or 'apartment' or 'hostel'); 'flight'; or 'tour', (the request can be either one of them or any combination of them, for example hotel and tour). Each of them is subset of 'resource'. For now, I stick the request for one destination only, and check-in & check-out date for accommodation as well as inbound-date & outbound-date for flight must be the same as begin-date & end-date for user request.
My questions as follows:
Firstly, in order to ensure check-in, check-out, inbound, and outbound date are the same as as begin-date & end-date for user request, all of them is mapped to beginning_of_journey and end_of_journey (please see the codes). Is this the correct way?
Secondly, I have a problem on how to code the constraint - tour date must be within begin-date and end-date of user request (so that the tour date must be within check-in, inbound, check-out, and outbound date as well). I define a set Date (sig Date) that has the fields day, month, and year where each of them has been defined as Integer. However, the problem is day can be negative number. And after executing the codes, the given instance seems weird. Could anyone please give a suggestion or advise me the right way to define that constraint?
Thirdly, I have a question that need to be clarified. Let say, the above problem has been resolved, and I need to initialise the specific request, for example tour date is July 1, 2016, date-begin is July 2, 2016 and end-date is July 4, 2016. Since I have defined the above constrained (Question No. 2), I want Alloy informs that the date given are violated. Is it possible to Alloy to do that?
I would really appreciate if anyone could give some comments and advice. Thank you
You need to test dates for sameness and for order. Unless you are trying to check the correctness of a design for calculating sameness and order of dates in the Gregorian calendar, however, there seems to be very little utility to modeling the internal structure of dates in Alloy.
So in your position I would, as Loïc Gammaitoni has already suggested, define an ordering on Date to support your queries on sequence.

Active Directory LastLogonTimeStamp Attribute is Way Off

I produced a report identifying stale accounts older than 60 days. For this time frame, I figured it is fine to use the LastLogonTimeStamp value from one DC. Even with the 9-14 day accuracy caveat, it serves the purpose.
The problem is, someone identified one account that didn't seem right. LastLogonTimeStamp for this account contained a date in July 2011. The user has not been with the company since 2010.
To resolve the discrepancy, I queried each and every DC for the LastLogon attribute. ALL of them are either Never, or they are in 2010.
I also queried each DC for LastLogonTimeStamp, and they are all identical, reporting the July 2011 date. LastLogonTimeStamp is correct for the vast majority of users, so there isn't an underlying replication issue.
So where on earth is this LastLogonTimeStamp coming from, and how can it be so wrong?
Any ideas?
Thanks much,
Sandra
Note that the LastLogon and LastLogonTimestamp attributes are not updated using the same logon criteria (i.e. logon types). See http://support.microsoft.com/default.aspx?scid=kb;EN-US;939899 which explains specifically why they may be different.
From The LastLogonTimeStamp Attribute – What it was designed for and how it works
The intended purpose of the lastLogontimeStamp attribute to help
identify inactive computer and user accounts. The lastLogon attribute
is not designed to provide real time logon information. With default
settings in place the lastLogontimeStamp will be 9-14 days behind the
current date.
LastLogonTimeStamp is the replicable attribute but this attribute is not updated every time a user successfully logs in. This attribute is updated only when its current value is older than the current time minus the value of the msDS-LogonTimeSyncInterval attribute.

Resources