FormCalc Date function doesn't returns current system date - date

How do I get date function to return date according to current system date?
Right now, with the code snippet below, it always returns UK time, not the current system date.
<calculate>
<script>$ = concat( num2date(date(), DateFmt()), " ", num2Time(Time(), TimeFmt()) )</script>
Any help is appreciated!

It's probably not UK time exactly, but rather GMT (or UTC, to use a more precise term). The UK happens to be aligned to GMT in the winter, but in the summer it advances one hour to BST for daylight saving time.
Now, I've never used LiveCycle myself, but nonetheless, I've read through the somewhat minimal docs for LiveCycle FormCalc Date and Time Functions, and the spec, and it appears to me that a few critical mistakes were made.
The date and time functions return UTC-based values, but only the time-related functions have been made aware of the local time zone. That is, there are separate Num2Time and Num2GMTime functions, but there is only one Num2Date function.
The Num2Date function works in terms of whole integer days, and thus they are simply days since 1900-01-01. Therefore, the number being passed in to the function must already be representative of the desired time zone. However, the Date function only gets the current GMT date. There does not appear to be a function to get the current local date.
It's different on the time side, because of the millisecond precision involved. However, there's yet another flaw here. Despite the docs saying that the Time function returning "the number of milliseconds since the epoch", its actually returning only the number of milliseconds since midnight GMT. There is no day-over-day accumulation of milliseconds from the date part. The docs here are even lying in their sample code which says:
Returns the current system time as the number of milliseconds since the epoch.
Time() => 71533235 at precisely 3:52:15 P.M. on September 15th, 2003 to a user in the Eastern Standard Time (EST) zone.
If that was indeed the case (and ensuring to use their 1900-01-01 epoch), the value would actually include an additional 3272572800000 milliseconds representing the days between 1900-01-01 and 2003-09-15, bringing the total timestamp to 3272644333235. Additionally, there's a typo there, because the timestamp they give is 3:52:13, not 3:52:15. Clearly nobody paid close attention to these docs!
The real problem is that one cannot be certain that the number of milliseconds since midnight of the current day in the local time zone is the same on every day. If instead of getting the current time, you were working with past stored time values, you might be an hour off (+ or -) if the current offset is different due to daylight saving time. Example: Eastern time might be UTC-5 or UTC-4, but only the offset currently in effect will be used by the Num2Time function, even if the date you're working with is using the other offset.
So, in summary, the Date function is insufficient, leading to your observations, and the date/time functionality in general is poorly designed. Given the constraints of this API, I can't even recommend a workaround. There would have to be a LocalDate function of some kind to be used instead of the Date function, but it doesn't exist.
The only advice I can offer is that it appears (from my research, not experience) that LiveCycle can use either FormCalc or JavaScript. So - use JavaScript instead.

Related

Why do I get different values in postgresql when using UCT values vs timezone names?

If I run this query:
SELECT ('2021-11-02 08:00:00+00' AT TIME ZONE 'UCT') at TIME ZONE 'UCT+2';
It gives this result:
2021-11-02 10:00:00+00
Which seems correct to me...
However, my timezone data comes in string format, for example: "Africa/Johannesburg", which I know is on the UCT+2 timezone.
But running this query:
SELECT ('2021-11-02 08:00:00+00' AT TIME ZONE 'UCT') at TIME ZONE 'Africa/Johannesburg';
Gives this result:
2021-11-02 06:00:00+00
Which is the opposite of what I expect to happen. I know I can write code to convert the strings to a UCT value but I don't understand why the string values seems to do the opposite of using UCT values. Could someone please explain why this happens?
Wow, there's lots to unpack here.
The main thing is that (to mis-quote Inigo Montoya) I do not think that UTC+2 means what you think it means.
One important thing here is the precise format.
You say you get this result:
2021-11-02 06:00:00+00
But What I get is:
2021-11-02 06:00:00
And that's really important because what I get doesn't include that +00. And that's because it's still 08:00 in the +00 time zone.
The AT TIME ZONE syntax says something like "What would a local at this place see the time being at this specific UTC time?". And someone in Johannesburg would see it as 10:00. Someone in London (in winter time) would see it as 06:00. But it's the same instant in time.
So the output of AT TIME ZONE doesn't usually have that time zone offset from UTC (+00) included in it.
Your conversions with two AT TIME ZONE clauses are redundant. Because it knows it's at that time zone, and hence what the UCT time is. You'll get the same result with one AT TIME ZONE clause (try it).
The reason why you get different answers appears to be because PostgreSQL does not interpret UCT+2 as the TimeZone that is 2 hours ahead of UCT. It interprets that as you specifying a POSIX time zone definition, which could also include daylight savings time rules etc.
This page: https://www.postgresql.org/docs/current/datatype-datetime.html says PostgreSQL will accept time zones specified in 3 ways:
Full name - e.g. 'Africa/Johannesburg'
Abbreviation - e.g. 'SAST'
Posix format, e.g. 'CET-1CEST,M3.5.0,M10.5.0/3' (This is, apparently, Paris)
Actually, it doesn't include the Posix format example, that's on this page: https://www.postgresql.org/docs/current/datetime-posix-timezone-specs.html
Basically, the posix format is a way of specifying the time zone rules.
Something like
[abbreviation][offset][daylight savings abbrev][DST offset][dst rules]
And so saying 'UCT+2' is probably "bad form" because you're trying to change the meaning of the abbreviation 'UTC' which has a standard usage.
You can verify that it isn't using the "UCT" part of your time zone to refer to the actual UCT time zone. If you do this:
SELECT ('2021-11-02 08:00:00+00' AT TIME ZONE 'BOB')
PostgreSQL will say it doesn't recognise time zone "BOB".
But if you do
SELECT ('2021-11-02 08:00:00+00' AT TIME ZONE 'BOB+2')
It'll happily give you 06:00:00. In fact, if you like, you can stick (almost) anything in there instead of "UCT". It doesn't get used in the calculation.
Note that the posix page I linked says
POSIX time zone specifications are inadequate to deal with the
complexity of real-world time zone history, but there are sometimes
reasons to use them.
Finally, 'UCT' is perfectly valid but it's doing my head in. I've only seen it as 'UTC', so TIL.

What is the standard for encoding a date as a timestamp?

Is there a standard for encoding a date as a timestamp? My thoughts:
This should be 12:00pm UTC in local time, eg 9:00am at T-3, therefore anyone consuming the timestamp, regardless of their -12/+12 offset, will recognize the same date, regardless of whether they parse at the UTC timezone
It could be 12:00pm at UTC
It could be the start of the day (12:00am) at UTC
It could be start of the day (12:00am UTC) in local time eg 9:00pm at T-3
Is there an official spec or standard to adhere to?
It would be easy to point to this document and say 'this is the standard' as opposed to being unaware and having to change our logic down the line.
There isn't a standard for this, because a date and a timestamp are logically two very different concepts.
A date covers the entire range of time on that day, not a specific point in time.
It may be a different date for a person in another time zone at any given point in time, but dates themselves do not have any association with time zones. Visualize a date as just a square on a calendar, not a point on a timeline.
Many APIs will use midnight (00:00) as the default time when a date-only value is assigned to a date+time value. However:
Whether it is UTC based or local-time based is very dependent on that particular API. There is no standard for this, nor is one answer necessarily better than the other.
Assigning a local-time midnight can be problematic for time zones with transitions near midnight. For example, in Santiago, Chile on 2019-09-08, the day started at 01:00 due to the start of DST. There was no 00:00 on that day.
Also, you tagged your question with momentjs. Since a Moment object is basically a timestamp (not a date), then Moment.js will generally assign the start of the day if provided a date-only value. The time zone involved is key to deciding which moment that actually is, which illustrates my prior points.
For example:
// Parsing as UTC
moment.utc('2019-09-08').format() //=> "2019-09-08T00:00:00Z"
// Parsing as Local Time (my local time zone is US Pacific Time)
moment('2019-09-08').format() //=> "2019-09-08T00:00:00-07:00"
// Parsing in a specific time zone (on a day without midnight)
moment.tz('2019-09-08', 'America/Santiago').format() //=> "2019-09-08T01:00:00-03:00"
Also keep in mind that sometimes APIs can be misnamed. The JavaScript Date object is not a date-only value, but actually a timestamp, just like a moment.

Subtracting the given specific time that changes the date :

I have to convert IST(India) to EET(Finland) timing using perl or shell ...
Means i have to subtract 3 hours,30 minutes from a given specific (ISD)time (not from the current time).
Time is in this format: YYYY-MM-DD HH:MM:SS
For ex: IST: 2016-01-01 02:30:00
Then after subtracting 3hours and 30 minutes ,I should get,
EET: 2015-12-31 23:00:00
The thing is after subtracting,if required the date,month and year should also change.
Can i do this using perl? Can anyone help me on this?
I'm not going to give you the actual code as you haven't demonstrated that you have made any effort to solve this yourself.
But the way to do this is to use a real Date/Time handling library. In Perl, that probably means DateTime. You can use DateTime::Format::Strptime to generate a DateTime object from a string.
In summary, your approach should be:
Parse your string into a DateTime object (being careful to ensure that the parsing object knows that the time zone is ISD (Icelandic time, I assume [Update: or, more likely, Indian]).
Convert the time zone in your parsed object to EET.
Use the parsed object's strftime method to produce the output time in the correct output.
Update: And I'll just add the standard advice about handling dates and times. You should always transmit and store dates and times in UTC. Local time zones should only every be displayed to users.

Jodatime: Getting milliseconds from date yields "Illegal instant"

val date = "01-10-1967"
val pattern = "dd-MM-yyyy"
val formatter = DateTimeFormat.forPattern(pattern)
formatter.parseMillis(date) // this line fails
The last line fails with:
Cannot parse "01-10-1967": Illegal instant due to time zone offset transition (America/Argentina/Buenos_Aires)
Any idea why?
(JodaTime version is 2.3)
The 1st of October 1967 was in Argentina a day where they changed from standard time to summer time, i.e. added 1 hour, on 00:00.
Since you are not providing a concrete time, I would assume that it defaults to exactly 00:00 which simply did not exist on that day.
Cf. the official faq:
What does 'Illegal instant due to time zone offset transition' mean?
Joda-Time only allows the key classes to store valid date-times. For
example, 31st February is not a valid date so it can't be stored
(except in Partial). The same principle of valid date-times applies to
daylight savings time (DST). In many places DST is used, where the
local clock moves forward by an hour in spring and back by an hour in
autumn/fall. This means that in spring, there is a "gap" where a local
time does not exist. The error "Illegal instant due to time zone
offset transition" refers to this gap. It means that your application
tried to create a date-time inside the gap - a time that did not
exist. Since Joda-Time objects must be valid, this is not allowed.
Possible solutions might be (taken from the faq):
Use LocalDateTime, as all local date-times are valid.
When converting a LocalDate to a DateTime, then use toDateTimeAsStartOfDay() as this handles and manages any gaps.
When parsing, use parseLocalDateTime() if the string being parsed has no time-zone.
Since you aren't interested in time information anyway, I think you might even want to replace formatter.parseMillis(date) with formatter.parseLocalDate(date). If for some reason you still need milliseconds, this Stack Overflow question might help.

Handling time zones in Cocoa

I just want to clarify if I am understanding how dates & time zones work.
Basically, I have a date string #"2008-07-06 12:08:49" that I want to convert to an NSDate. I want this date and time to be in whatever the current user's time zone is set in. So if they are in GMT or HST, it's still 12:08:49.
If I have date in unix form 1215382129 (UTC) and my time zone is set to London (GMT), the outputted date from NSLog() is:
2008-07-06 12:08:49 +0100
If I then change my time zone to Hawaii (HST) and output the same date, I get:
2008-07-06 12:08:49 -1000
This seems to work fine, but I was under the impression to get the time in Hawaiian, I'd have to physically add the time difference (-10hrs) to the unix time stamp. Is this not required then?
Does that mean, whatever date and time a unix time is pointing to, it always points to the same date and time in whatever time zone a user is in?
Hope this makes sense!
Edit
I've just realised (thanks to Kevin Conner!) that in fact NSDateFormatter is creating different unix timestamps for that date string depending on the current timezone! So I was totally wrong!! :-)
Disclaimer, I'm mostly a Java guy. But Cocoa seems to work like the Java library in this regard: Dates are zoneless timestamps. Time zones are in the domain of formatting dates for display. In other words, the internal format doesn't consider time zones, it's all in UTC. Time zones are relatively a convenience for humans, so they are in the display/parsing side.
I noticed there is a setTimeZone: method on NSDateFormatter. Try calling that on your formatter before performing the format.