Json object: is putting a date as string a bad practice? - spring-mvc

I have the following json object:
public class User {
private String name;
#JsonFormat(pattern="dd-MM-yyyy")
private Date birthdate;
}
but I'm thinking of changing it to:
private String birthdate; //mmm...now need to make sure the format is respected..
Problem is that this object has to be saved inside of a DB and then retrieved.
Suppose I have an user in the CEST time, while my application's time is UTC, so 2 hours behind.
They send "15-04-1990" (time is implicitely 00:00:00), the system then interprets this date as "14-04-1990"(time is implicitely 10:00:00 PM) due to the 2 hours difference.
When they go retrieve the information again they will see 14-04-1990!
Ok, I could just add the sender's timezone to the request. But I don't like it: take a 3rd party residing on the application's country wanting to check some information (for example an helpdesk operator): they would still see the date in the wrong timezone!
So, do you see any problem in receiving the date as string?
And if that would be fine how to make sure that the string contains a date formatted in "dd-mm-yyyy"?

One of things could be to save the date and time objects as timestamp of GMT and then change every time zone with respect to that.

Related

How can I get SignalR to stop changing my date/time values?

I have a simple class that contains a DateTime property. When I set the value of this property using DateTime.Now() the value is correct. However, when I pass this class object as a parameter via SignalR, on the receiving end SignalR has changed the DateTime so that it no longer matches the original DateTime. How can I get SignalR to stop manipulating my DateTime values? This issue seems to have started with a recent update to the latest SignalR nuget packages.
This seems to be a problem when the hub and the client are in two different time zones. It seems Microsoft is trying to help, by adjusting the date/time to the local time zone, but I want the original value, not the value Microsoft "thinks" I want.
When you want two systems to communicate with each other I would recommend using always the DateTime in UTC for various reasons. In your case you have two options here:
1 - Send the date as string string date = DateTime.Now.ToString(CultureInfo.InvariantCulture); so on the client side you just need to parse the datetime like DateTime.Parse(date, CultureInfo.InvariantCulture);.
2 - Send the date in UTC like DateTime.UtcNow; so event if the SignalR tries to change the date, it will have the DateTime.Kind as UTC. In this case or you will get the current date correctly, or you just adjust on the client side to the local time like receivedDate.ToLocalTime();
This one was a real head scratcher as I had the exact same issue. The client was storing the correct time but by the time it hit the Hub... it had changed. I'm really glad you posted this as I wouldn't have imagined this issue being possible. #Kiril1512 posted the correct resolution. In my case I used his second option as I didn't want to change my model... although simply converting to a string would have been simpler. While I did follow his suggestion and convert everything to DateTime.UtcNow()... I am thinking this was unnecessary as I noticed even previously stored dates converted correctly. This makes me think that either this isn't necessary to do, or dates are converted to Utc when they hit the Hub automatically which may be what the issue was to begin with?
Either way I posted this as I discovered that converting this date back to Local time was a little more involved. Here is how I ended up doing the conversion which resolved this issue for me that I gathered from this resource:
DateTime convertedDate = DateTime.SpecifyKind(
DateTime.Parse(msg.CreatedOn.ToString()),
DateTimeKind.Utc);
var kind = convertedDate.Kind;
DateTime dt = convertedDate.ToLocalTime();

spring.jackson.date-format add extra 4 hours to given input

I want to format java.util.Date.I get year month and day correctly but when I insert data to database I get 4 more hour.For example if I insert 2017-12-18 12:00
then inserted row will be 2017-12-18 16:00
My controller:
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String insertRequest(#RequestBody EmployeeRequest employeeRequest) {
System.out.println(employeeRequest.getDate());
requestService.insertRequest(employeeRequest);
return "inserted and sent mail";
}
My model :
#NotNull
private Date date;
My application.properties
spring.jackson.date-format=yyyy-MM-dd HH:mm
Thanks in advance
This is not a date formatting error, this is very likely related to TimeZone. Depending on how your Database and Application Server are configured it appears that they are using different default timezone's.
Have you tried reading the data back OUT of the database into Java? If the database is properly storing the timezone then it should Just Work when you read it back into your java object. If not, i'd suggest first updating your Date/Time format to include the timezone e.g. spring.jackson.date-format=yyyy-MM-dd HH:mm:ssZ. Then the database should at least have access to the appropriate timezone.
If this doens't work, the proper mitigation really depends on your application and how it needs to make use of time / timezones. It could be that what you have is actually fine, it's just that when you manually inspect the database it's displaying to you the time in the default timezone. You could also just set your database and app servers to use the same timezone, but this can be a configuration nightmare.
Side note: as some general advice, I'd high recommend using either java.time.* or jodatime libraries instead of java.util.Date if at all possible. This isn't related to this specific issue, but they are much more robust date/time libraries than the legacy java.util.Date

MS JSON date serialization and daylight saving time

We have an Ajax web service hosted in an ASP.NET application. This service accepts a DateTime parameter which, for the purposes of this question, should receive the DateTime equivalent of /Date(1359727200000-0200)/, which is a MS-JSON literal for Feb 1, 2013 9:00 AM in Brazil time. This literal is what the browser sends within the Ajax request.
But instead of receiving that date and time, the argument passed to the service method is Feb 1, 2013 12:00 PM. To make matters worse, the argument's DateTimeKind is Local. It would be understandable if it were Utc, but even that would be incorrect since February 1st is daylight saving time in Eastern Brazil, so that 9:00 AM (local) sould be 11:00 AM (UTC). It really is a mess. By the way, the web server runs under Eastern Brazilian time zone.
Is there any ASP.NET configuration, service method annotation, specific client instructions, or any framework resource to work around this problem?
After much debugging I found the problem: I was ignorant of the way the JSON serializer works regarding the System.DateTime kind and the Date literal when (de)serializing dates back and forth between the server and the browser.
In detail, here's what happens. Suppose a service has to return a DateTime value to a client in JSON format. The DataContractJsonSerializer will produce a string in the (infamous) /Date(UTC ticks)/ format, which the client can parse into a JavaScript Date value. This serialization is sensitive to the DateTime's Kind property:
When the Kind is DateTimeKind.Utc, the string literal will contain "/Date(UTC ticks)/" and no time zone.
When the Kind is DateTimeKind.Local, the string literal will contain "/Date(UTC ticks-time zone)/".
If the Kind is DateTimeKind.Unspecified, it is assumed Local.
Conversely, if the client sends a date value to the service, the serialization process is also sensitive to the "kind" of the JSON literal:
When the literal is in the format "/Date(UTC ticks)/" with no time zone, the produced
DateTime will be of DateTimeKind.Utc kind.
When the literal is in the format "/Date(UTC ticks-time zone)/", the produced DateTime will be of DateTimeKind.Local kind.
All I had to do is make sure the client sends only UTC-formatted Date literals to the service. All is great now.

ASP.NET WebAPI XmlFormatter Missing UTC Offset for Dates

I have an ASP.NET WebAPI implementation that I am allowing clients to consume and request either XML or JSON formatting of the HTTP response. Some of the response objects include date/time values. I have been successful in getting the JSON response to include a proper ISO 8601 formatted date (including UTC time offset) by using code like:
Dim json As JsonMediaTypeFormatter = _
GlobalConfiguration.Configuration.Formatters.JsonFormatter
json.SerializerSettings.DateFormatHandling = _
Newtonsoft.Json.DateFormatHandling.IsoDateFormat
json.SerializerSettings.DateTimeZoneHandling = _
Newtonsoft.Json.DateTimeZoneHandling.Local
The JsonFormatter now gives me a date like this:
2008-11-03T14:14:00-05:00
However, the XmlFormatter gives me a date like:
2008-11-03T14:14:00
Notice the missing UTC time offset ("-05:00"). How do I get the XMLFormatter to give me the UTC time offset?
I believe I just figured this out myself.
When reading the dates from the SQL Server database (using an IDataReader) and the Enterprise Library Data Block, I need to use the Date.SpecifyKind method to tell what kind of date is being retrieved from the database.
Dim dateCreated As Date = _
Date.SpecifyKind(CDate(dbReader("DateCreated")), DateTimeKind.Local)
By doing this, I was also able to remove the JsonMediaTypeFormatter lines specified in my original question. So, now both XML and JSON send the date as:
2008-11-03T14:14:00-05:00
More information on Date.SpecifyKind can be found here:
http://msdn.microsoft.com/en-us/library/bb546101.aspx

How to show a UTC time as local time in a webpage?

I have a database that holds a time as UTC. This time can be shown in a webpage, so I’ve been asked to show it as local time in the page as it can be viewed from any country. A colleague mentioned something about getting the country settings from the current thread (on the server) but I couldn’t find any details on this. Is what I want to do possible?
If you (and your website) are comfortable with javascript, there is a very easy way to accomplish this.
First, on the server side, you would have the UTC date/time formatted in RFC 3339 format (the standard for internet time used by, among other protocols, icalendar). The basic syntax of RFC 3339 is:
YYYY-MM-DDTHH:MM:SS
Such that where I am, the time would be:
2010-05-04T05:52:33
But when the time is not local, but UTC, you add a Z to the end to denote this. So in my case, since I'm at -0500 hours from GMT, the same time above would be:
2010-05-04T10:52:33Z
So, first you get the server to output the above to your web page's javascript. The javascript can then parse that timestamp and it will output the date and time adjusted to the browser's time zone (which is determined by the computer hosting the browser). You should remember that if a user is from Tokyo and is viewing your website in Spain, they will see the timestamp in Tokyo time unless they've adjusted their computer's clock.
So the javascript would be:
var time_string_utc = some_server_variable; // timestamp from server
var time_string_utc_epoch = Date.parse(time_string_utc);
var time_utc = new Date();
time_utc.setTime(time_string_utc_epoch);
At this point, you have a javascript date object set to your UTC timestamp. A quick explanation of what happens above:
The first variable assumes you have passed the timestamp string to that variable from the server.
The second variable uses the Date.parse() method to convert the string to an epoch timestamp.
The third variable creates the unset Date object.
The last line line uses setTime method, which sets a Date object from an epoch timestamp.
Now that you have the object, you can output it to the user as you see fit. As a simple experiment, you can use:
document.write(time_utc);
which, if you are in my timezone using the UTC timestamp I started off with:
2010-05-04T10:52:33Z
would give:
Tue May 04 2010 05:52:33 GMT-0500 (CST)
but you can use various javascript methods to format the time into something much more pleasant looking.
No need to guess the user's country or even adjust your timestamp, so long as you trust the user's local browser/computer time zone.
Again, the short version:
var time_string_utc = some_server_variable; // UTC time from server
var time_string_utc_epoch = Date.parse(some_server_variable);
var time_utc = new Date();
time_utc.setTime(time_string_utc_epoch);
document.write(time_utc);
Also consider reading this thread which dives deeper in the dos and donts of handling daylight saving problem across timezones
Of-course is possible. You just need to find that country settings to detect the country your user comes from, and then modify the displayed date to fit that country's time.You can also find another way to detect the user country.(maybe from his ip address).
I am sure that the best way to manage this is let your colleague know that you need more details about the country settings implementation on your project and how can you use it.
EDIT:
Thinking about it I don't think it is possible to display the local time once you have the client’s culture. I'd certainly be interested to see your colleagues suggestion.
Getting the US culture, for example, won't help as the US has many timezones.
I think using Javascript like Anthony suggests would be the way to go...
OLD:
You can override the InitializeCulture() method with code that sets the current (chosen or browser reporting) cultures:
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(selectedLanguage);
Thread.CurrentThread.CurrentUICulture = new
CultureInfo(selectedLanguage);
this is how I've done it in PHP in the login file which connects to MySQL database:
//set local timezone
date_default_timezone_set('America/Denver'); //use local TZ
Then, every time you access the DB, you are setting the timezone for that session and any input/output associated with it.

Resources