Converting ZonedDateTime to string - java

I need to store the current time as a String in a database. The time can be in different timezones, so I'm looking at using Java SE 8's new ZonedDateTime class.
I notice that the toString() method automatically outputs:
2016-04-15T17:40:49.305-05:00[America/Chicago]
This also seems to be readable by ZonedDateTime.parse() and convert to the right values.
If all I am doing is storing these values and I don't need to ever convert the value to a user-readable format, is this all I need to do to accurately store data with proper timezones? For example, if I insert two ZonedDateTimes into an SQL database by storing their toString() representations, and I later read in these times by using ZonedDateTime.parse(), can I expect things like isAfter() and isBefore() to work just fine?
Or am I missing a step in between? After trying to figure out timezones in Java 7 this feels almost too easy.

Generally speaking I would avoid relying on parsing the toString() representation of any class in my application.
toString() is meant to provide a human readable version of a class so it's subject to change from relase to release.
I would suggest you to force the format to be the one that you expect, e.g applying:
String toStoreInDb = DateTimeFormatter.ISO_ZONED_DATE_TIME.format(zonedDateTime);
...
ZonedDateTime fromDb =
ZonedDateTime.parse(stringFromDb, DateTimeFormatter.ISO_ZONED_DATE_TIME);
This way your application will resist to any toString() change.
Moreover take a look at this bug:
Bug in ZonedDateTime.parse()

Yes, that will accurately store the date, and using the .parse() method will allow you to use the other methods of ZoneDateTime. Though if you want to be able to use sorting functions with your db then you will need to either manually convert the ZonedDateTime into a timestamp or use your ORM's features to do it for you.

Related

Convert country-state code to time zone in Java

Having country-state code as input, is it possible to get the timezone using Java?
For example us-tx -> (GMT-6)
Tried using this answer, however this method uses only the country code, without the state and the output is :
US/Alaska_US/Aleutian_US/Arizona_US/Central_US/East-Indiana_US/Eastern_US/Hawaii_US/Indiana-Starke_US/Michigan_US/Mountain_US/Pacific_US/Pacific-New_US/Samoa
This isn't possible - in any language. Many US states have more than one time zone, depending on which part of the state you are referring to:
From Wikipedia:
You can clearly see on this map, many states where the time zone boundary does not follow the state boundary.

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to java.time.LocalDateTime

Calling the service from Android passing LocalDateTime type parameter.I'm getting this expection while casting request parameter which was send as same Type(LocalDateTime) to LocalDateTime.
here is what i'm doing
#PostMapping(value = "/getDates")
public Object getDates(#RequestBody Map<Object, Object> request) {
LocalDateTime startDate = (LocalDateTime) request.get("fromDate");
LocalDateTime endDate = (LocalDateTime) request.get("toDate");
}
API Request
{
"fromDate":LocalDateTimeObject
"toDate":LocalDateTimeObject1
}
The cast operator does 3 different things: Primitive conversion, typecheck, and type assertion.
These 3 things are like guns and grandmas: Utterly, completely, entirely unrelated. They look similar. It ends there.
The only one of those 3 that actually converts things, is primitive conversion. As the name indicates, this one happens if the thing int the parentheses is a primitive type, such as 'int'.
In other words, (LocalDateTime) foo is typecheck: It checks if foo is a LocalDateTime. If yes, nothing happens. If no, a ClassCastException is thrown.
It looks like you expect it to convert the "fromDate" parameter to a LocalDateTime - a cast is not how you can accomplish this.
JSON can only represent booleans, numbers, strings, arrays, and maps. It cannot represent date time objects. That means that your API should define how to do this. The usual way is via string, by putting in the spec that datetimes are passed for example as: "2020-05-20 14:00". Or possibly as a number: Number of milliseconds since 1970, at UTC, then take the local datetime you find there, and that's what I meant. That is a bit more unwieldy, but it's your API, you get to spec it however you want.
From your error, it looks like you've just tossed a LocalDateTime object at a JSON marshaller, which turned it into a convoluted map structure representing the fields of the LDT object.
This is not workable; I strongly suggest you retool this.
Your first step is to figure out what your spec is. Once you've determined this, your second step is how to convert the string or millis-since-epoch you get into an LDT instance (or if you insist, this map structure).
If it's a string with year-month-day, use java.time.format.DateTimeFormatter to make the appropriate pattern (check the constants, one probably is good to go here), and use that: LocalDateTime.parse(request.get("fromDate"), DateTimeFormatter.ISO_LOCAL_DATE_TIME)
If you have epoch millis (I don't recommend this), Instant.ofEpochMilli(Long.parseLong(request.get("fromDate"))).atZone(ZoneOffset.UTC).toLocalDateTime().
Use the same library (presumably, GSON or jackson) to demarshal the map that you used to marshal it. Whatever the client sent you? They are using one of those two libraries. Use the same and reverse the operation.
I strongly recommend option #1.

Print a Duration in human readable format by EL

First of all I'm new to java.time package.
I'm writing a webapp that need to work with specific times of the day and with several durations of events.
So I wrote my code using LocalTime and Duration classes of java.time package.
When I need to render their value in JSP it is very simple for LocalTime object (because .toString() returns a human readable vale), so I can just write ${startTime} and everything goes in the right way (e.g. it is rendered as 9:00).
The same approach doesn't work for Duration, because its representation is something like PT20M (in this case for 20 minutes).
Does it exist an elegant way to perform a human-readable conversion in JSP directly by EL?
Yes, I know I can convert the object in a string in my classes (before JSP), but I'm searching for the suggested approach (that I'm not able to find)... another point is that I not see an official "convert()" (or whatever else) method in Duration object... so I'm thinking I'm using the wrong object to map a duration of time (to add or subtract on LocalTimes).
Thank you.
Unfortunately there exists no elegant builtin way to format a Duration in Java 8. The best i have found is to use the method bobince describes in this answer:
Duration duration = Duration.ofHours(1).plusMinutes(20);
long s = duration.getSeconds();
System.out.println(String.format("%d:%02d:%02d", s/3600, (s%3600)/60, (s%60)));
Which prints:
1:20:00
The code will have to be tuned if you need longer durations.
I'm not sure what you mean that you are missing a convert method, but Duration is well suited for adding/subtracting on LocalTime. The methods LocalTime.plus() and LocalTime.minus() accepts Duration as argument.
If you're interested in words, apache commons will do the trick:
DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - start, true, false))
2 days 1 hour 5 minutes 20 seconds
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/time/DurationFormatUtils.html#formatDurationWords-long-boolean-boolean-

Common datetime formats in log files

I'm looking for a list of common datetime formats used in logs (e.g. webserver, database, etc).
Even better would be a (java) library that can extract date and time from a given string ( < 10KB).
Does anyone know a good one?
this library is likely a good place to start: SimpleDateFormat
The docs contains the an introduction to the standard datetime format strings. But as #Olaf points out, you're going to need to specify what the format is beforehand or there is literally no way differentiate certain dates from one another.
Looks like what you'd want to do is construct a range of date formats that might match, apply all of them to a date string, then see which date is closest to Datetime.now().
Although this doesn't answer your question directly, but Java includes libraries for working with regular expressions. It would be pretty easy to write a library of your own based on that. I've has a lot of success extracting all sorts of data using regular expression. It would certainly be less than 10kb and would require no external dependencies other than the JDK.

Java TIMESTAMP has trailing zeros, how do I remove?

I'm using Java with hibernate and am in the early stages of learning how everything works. I'm getting there slowly but I have had some trouble with dates in Java.
My current problem is that when I get a timestamp from a MySQL database it seems to have a load of extra zeros on the end. When I pass this through to PHP (yes its a Java/PHP application we're writing) then formatting the date ends with an incorrect result.
Here's what I see:
2000-08-10 14:09:21 // Time in database
965912961000 // Timestamp from Java of this time
965912961 // The PHP equivalent of the database timestamp - using strtotime()
In the Java model I have the variable setup like this:
#Temporal (TemporalType.TIMESTAMP)
private Date logTime
So my question is how do I get rid of the three trailing zeros? Obviously I could remove these with PHP but I'd rather it came from the back-end Java if possible.
It's not clear why you're formatting the Date into an integer, but it's a simple fact of life that a Java Date is measured in milliseconds - whereas presumably a PHP one is measured in seconds (since the Unix epoch).
That's an internal representation though, which most of the time you shouldn't care about. If you're transmitting that integer, feel free to just divide by a thousand to convert it from a milliseconds-based representation to a seconds-based representation.
If you can be clearer about how you're seeing the integer to start with, we may be able to help more.

Categories