wrong timezone when loading joda Instant field via JPA - jpa

In my Play application I have a model with a created field of type Instant. It's populated using a #PrePersist hook which just sets it to a new Instant(). The default timezone is correctly detected as US/Chicago, and when persisted to mysql it appears in the same timezone (in a datetime field).
However, when the object is read back from the database and the time is displayed, it's shown in UTC rather than local time. I'm currently displaying it using
${org.joda.time.format.DateTimeFormat.forStyle("SS").printTo(out, object.created)}
Being new to Joda and fairly new with JPA, I'm not sure if this is a joda problem, a JPA problem, if I should be using a different Joda type, a different mysql type, or if I'm going about this completely wrong. Can someone point me in the right direction?

According to the API UTC seems to be the reference timezone. You can always change that on the DateTimeFormat itself with the withZone(DateTimeZone) method. The following code outputs the date in America/Chicago which seems to be the right timezone in joda-zime:
${org.joda.time.format.DateTimeFormat.forStyle("SS").withZone(org.joda.time.DateTimeZone.forID("America/Chicago")).printTo(out, object.created)}
Following the user guide you can also set the default timezone for joda with DateTimeZone.setDefault(DateTimeZone.forID("America/Chicago")); but I always thought that specifing the default timezone with an VM argument works too and should be the better option.

Related

Cannot use NodaTime's Instant.InZone with the DateTimeZone in a variable with Npgsql's Entity Framework Core provider

So I'm running into a rather odd issue here. I've got a PostgreSQL 14 server and I'm using the Npgsql Entity Framework Core provider to access it. If I have an Entity Framework Core entity that contains a date as a NodaTime Instant type (which becomes timestamp with time zone in the database) and try to project that via .InZone(timeZone).LocalDateTime, I run into 3 situations.
Actual example query would be something like this:
await context.Entities.Select(e => e.Date.InZone(<timeZone>).LocalDateTime).ToListAsync();
(Although it seems that not including the .LocalDateTime portion has no bearing on the below situations, with the exception of when .InZone(<timeZone>) is replaced with .InUtc().)
The first situation, if in place of <timeZone> I make an explicit call to DateTimeZoneProviders.Tzdb.GetSystemDefault(), then the above query succeeds without issue. (Although oddly, when I look at EFCore's generated SQL, I do not see AT TIME ZONE like the Npgsql docs mention, but I do see it if I was to replace the .InZone(<timeZone>) call with .InUtc().)
The second situation, if in place of <timeZone> I put in a reference to a static variable containing the result of DateTimeZoneProviders.Tzdb.GetSystemDefault(), then I get an InvalidOperationException with the following message:
The client projection contains a reference to a constant expression of 'NodaTime.TimeZones.CachedDateTimeZone' which is being passed as an argument to the method 'InZone'. This could potentially cause a memory leak; consider assigning this constant to a local variable and using the variable in the query instead. See https://go.microsoft.com/fwlink/?linkid=2103067 for more information.
Given the above, I run into the third situation, if in place of <timeZone> I use a local variable that contains either the result of DateTimeZoneProviders.Tzdb.GetSystemDefault() or the static variable I mentioned above, then I get an InvalidOperationException with the following message:
Expression '#__timeZone_0' in the SQL tree does not have a type mapping assigned.
Am I doing something wrong here? My expected goal is to be able to take the Instant that I'd get from the database's timestamp with time zone and have it be either a ZonedDateTime or LocalDateTime on the client end, without needing to go through extra steps on the client end after obtaining the data from the database. Right now I would have to get the date from the database using .InUtc().LocalDateTime and then after the list has been materialized, I'd be able to do conversions on the returned values.
The NodaTime plugin doesn't support passing parameterized time zones from .NET; you can only use a constant expression such as DateTimeZoneProviders.Tzdb["Europe/Berlin"] (see these docs for supported translations). You can use this to convert a PG timestamp with time zone into a timestamp without time zone in PG, and then retrieve the result as a timestamp without time zone, which can be read as a NodaTime LocalDateTime.
However, if what you're looking for is to get a ZonedDateTime/LocalDateTime with the time zone of the client machine (where .NET is executing), then doing .InUtc().LocalDateTime is the way to do that - any reason you're trying to avoid it?
A bit more context (as well as a full code sample) could shed some more light on what you're trying to achieve.

Cloud Function writing wrong time on firestore

When I write a Timestamp on Firestore it shows 6.00PM on database though I have not defined any time in the Date object.
My Approach to get Timestamp from date :
let reservationDate = new Date(year,month,dayOfMonth);
let bookedRoomData = {
....
...
reservationDate: admin.firestore.Timestamp.fromDate(reservationDate),
...
};
What is the reason behind showing 6.00PM instead of 12.00AM ?
What should be done to fix this?
Screenshot of database is given bellow -
Since you tagged this google-cloud-functions, I'm assuming that your code is running in Cloud Functions.
When you create a new Date object on any machine, it uses the local machine's sense of timezone. So you're making a date at midnight in whatever timezone has been assigned to your Cloud Functions instance. It's not the timezone where you're computer's clock is set.
When you see a timestamp in the console, it's always going to appear on your computer's clock's configured timezone. So, your computer is 6 hours behind whatever is being used by Cloud Functions.
If you want a specific time, you should make sure your Date is configured that way. Consider using a library such as momentjs to create dates according to timezones of your interest. Bear in mind that Timestamp objects do not encode a timezone. They just render in the console according to your local timezone.

QuickFIX - set StartTime\EndTime

QuickFIX has a configuration file where you set StartTime and EndTime. Unfortunately AFAIK QuickFIX only supports UTC for this configuration, whereas exchanges are often timezone dependent. This means that you need to remember to update this configuration file every time the clock changes.
Is there a way to set the StartTime \ EndTime parameters programatically instead of through the configuration file? That way you could adjust the timeset the correct values programatically.
There is a way to set this. You can can set a timezone as follows:
TimeZone=America/New_York
see the configuration guide.
It is weird that it is not in the quickfix configuration guide and it is present in the quickfixJ guide.
in our production environment we use always UTC times.
In the QuickFIX config file add for every counterparty the following line:
UseLocalTime=N
Please read the documentation here:
http://www.quickfixengine.org/quickfix/doc/html/configuration.html#Session
as per quickfix docs you should add
set UseLocalTime=Y
Indicates StartTime and EndTime are expressed in localtime instead of
UTC. Times in messages will still be set to UTC as this is required by
the FIX specifications.
We had an error
System.ArgumentException: Only UTC time is supported
Parameter name: oldtime
at QuickFix.SessionSchedule.IsNewSession(DateTime oldtime_utc, DateTime testtime_utc)
at QuickFix.Session.get_IsNewSession()
and the only way to fix it was to delete the store directory. Presumably the session timestamp like this

GWT Date Handing... have client respect server's timezone

I've read many a post here re: GWT date handling.
One in particular that struck a cord with me was this one
Sending a date and timezone from GAE server to GWT client
Anyhow, there's a need on a project I'm working on to be able to display days, hours, minute intervals as labels in a grid. My team has adopted an approach where all date/time instances are passed the client from the server in ISO8601 String format. The server time zone is to be respected by the client. The biz use case is that all date/time instances are in "market time", so that any browser that visits the app will see and work with dates in the "market time" timezone which happens to be GMT-05:00 (if Daylight Savings in effect) or GMT-06:00 (if Standard Time in effect).
I have posted some source on Github, here:
https://github.com/fastnsilver/gwt-datehandling-example
Particularly...
https://github.com/fastnsilver/gwt-datehandling-example/blob/master/src/main/java/me/fns/gwt/datehandling/client/util/CSTimeUtil.java
and the GWTTestCase
https://github.com/fastnsilver/gwt-datehandling-example/blob/master/src/test/java/me/fns/gwt/datehandling/client/util/CSTimeUtilTestGwt.java
in the hopes that someone can stare at the utility (and test) we're employing for date handling and help us see what we're not seeing.
EDIT
The basic problem is that CSTimeUtil#hoursInDay(Date) is not being calculated correctly in Production mode for "transition days" This method is used by other methods (like CSTimeUtil#dateToHour(Date) and CSTimeUtil#labelsForDay(Date)).
I have deployed our application with the current implementation of CSTimeUtil and it appears to work, but not quite. I'm really confused by alternate test results when e.g., mvn gwt:test is run in GWT Mode or Production Mode on Windows where the OS timezone is set to various timezones other than U.S. GMT-05:00 or GMT-06:00.
Based on some hints from Andrei and some serious blood, sweat and tears, I figured this out on my own. I have updated the code in Github, so if you're curious please go have a look there.
The basics:
Make sure all Strings are ISO8601 (no millis) compliant when sent from server to client and vice versa
Use DateTimeFormat.getFormat("yyyy-MM-ddTHH:mm:ss.SZZZZ") to format and parse dates
Retreive GMT-prefixed time zone info from java.util.Date in "Market time" using DateTimeFormat(Date, TimeZone), where TimeZone param is set as TimeZone.createTimeZone(TZ_CONSTANTS_INSTANCE.americaChicago()) and time zone String retrieved by TimeZone.getISOTimeZoneString(Date)
Generating days, see generateDay(Date, int) or hours generateHour(Date, int), from a source date had to take into consideration that an increment or decrement coudl trigger a change in time zone offset if occurring on a "transition day".
If you time zone is fixed, why would you use a string to represent date/time? You can send a standard Java Date object to the client. If you want, you can even store all dates and times as Longs and pass Longs only. You also send the GWT's TimeZone Json string for your time zone (once per session). You can find it in the GWT - there is a file with strings for all time zones.
On a client you use DateTimeFormat with many predefined formats to display whatever you need: full date, month and date, date and time, etc. Just remember to create TimeZone object from this Json string and use it in DateTimeFormat.getFormat(...).format(Date, TimeZone).
With this approach you don't have to worry about DST changes (they are encoded in that Json string) and locales. You only pass simple Date or Long objects.

passing timezone from client (GWT) to server (Joda Time)

I'm using GWT on the client (browser) and Joda Time on the server. I'd like to perform some DB lookups bounded by the day (i.e. 00:00:00 until 23:59:59) that a request comes in, with the time boundaries based on the user's (i.e. browser) timezone.
So I have the GWT code do a new java.util.Date() to get the time of the request, and send that to the server. Then I use Joda Time like so:
new DateTime(clientDate).toDateMidnight().toDateTime()
The trouble of course is that toDateMidnight(), in the absence of a specified TimeZone, will use the system's (i.e. the server's) TimeZone. I've been trying to find a simple way to pass the TimeZone from the browser to the server without much luck. In GWT I can get the GMT offset with:
DateTimeFormat.getFormat("Z").fmt(new Date())
which results in something like "-0400". But Joda Time's DateTimeZone.forID() wants strings formatted like "America/New_York", or an integer argument of hours and minutes. Of course I can parse "-0400" into -4 hours and 0 minutes, but I'm wondering if there is not a more straightforward way of doing this.
You could use java.util.Date's getTimezoneOffset() method. It's deprecated, but that's pretty usual for Date handling in GWT currently.
And AFAIR, you can specify something similar to "UTC+4" in Joda time.
Update: I looked it up, and it's "+04:00". Or use DateTimeZone.forOffsetHours() or even forOffsetMillis().
Gwittir (http://www.gwtsite.com) is a library for GWT that includes many cool utilities, like databinding, animation, reflection, and more. However, there are some other interesting goodies as well like the new Joda Time integration. If you have ever been frustrated by GWT’s lack of java.util.Calendar support, you’ll love this, as it makes it easy to do date manipulations in your applications.
otherwise, there are other ways to get timezone offset with + & -.
import java.util.TimeZone;
use: TimeZone.getDefault().getRawOffset()
this function will return the offset time in millisecond about your phone seeting. For Example, GMT-04:00 is equals to (-4)*60*60*1000 = -14400000.
After some operations to get the number which you want.
I have a similar but slightly different problem I think.
I actually need to store the clients timezone on the server, so that I can send out messages about dates stored in their calendar.
The dates are stored in UTC time in google app engine and of course I can store the current Timezone offset when creating the appointment. The problem comes when for instance I want to send out a summary email with a list of upcoming appointments in it. These appointments need to be offset with the correct Timezone adjustments for the client (Im happy to assume that they are still in the same timezone as when they created the appointment).
The real problem comes with Daylight Savings adjustments, so for instance I might have appointments stored for Saturday 30th October 2010 at 1pm (BST[GMT+60]) and Monday 1st November 2010 at 1pm (GMT).
So as you can imagine, I cant just use the current timezone offset (BST) as that would mean that the appointment on Monday 1st November would be listed as 2pm rather than 1pm (GMT+60)
It occurs to me that the best way to deal with this is just to store the timezone offset with each appointment individually, but I feel it would be much better to be able to determine the original timezone correctly in the first place, then just let java do the correct adjustments.