Print a Duration in human readable format by EL - java

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-

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.

How many days from now is the Duration?

I have a Duration, like P3M (3 months). How can I get number of days it is from now?
All I have now is this:
Duration.parseWeekBasedPeriod("P3M")
I know the period parameter will never be shorter than 1 week, so parseWeekBasedPeriod() should be ok. But I'm reading JavaDoc, and I can't figure out how to get those days.
I understand, the problem is that months can has 31, 30, 29 and 28 days.
Using parseWeekBasedPeriod(...) is certainly wrong if you want to apply durations measured in months. This very special method handles week based years which can last either 364 or 371 days (52 or 53 weeks). So I suggest just to use the standard parsing method for calendar-based durations. The following code also strongly simplifies the evaluation of days between two dates (see last line).
Duration<CalendarUnit> duration = Duration.parseCalendarPeriod("P3M");
PlainDate today = PlainDate.nowInSystemTime();
PlainDate later = today.plus(duration);
long days = CalendarUnit.DAYS.between(today, later);
By the way, I have tested the method for weekbased durations once again. It will usually throw an exception if it tries to parse months. You didn't seem to have seen any exception so I assume that the fact that you use untyped constructs like "val" has shadowed the necessary type information in processing the duration string (and Time4J is a strongly typed library). Hence - if technically possible for you -, I strongly recommend to use type-safe code as shown in my solution.
Finaly figured it out:
val period = Duration.parseWeekBasedPeriod("P3M")
val start = PlainDate.nowInSystemTime()
val end = start.plus(period)
val days: Long = Duration.`in`(CalendarUnit.DAYS).between(start, end).getPartialAmount(CalendarUnit.DAYS)

How to manipulate Ranges of Time of a Day

I'm working with an agenda in Java. I have stored in my database the day of the week, the start and end time of some labs availability.
Now I need to provide a service for a schedule system by showing only the unavailable times of the day. For example, if day one has start time 13:00 and end time 19:00, I need to return a range just like this:
[00:00 - 13:00, 19:00 - 23:59] . Remembering that a day can have more than a range available.
Is there any Java Class or API that could help me on subtracting these ranges?
My lib Time4J offers following solution for the subtraction problem:
ClockInterval fullDay = ClockInterval.between(PlainTime.of(0), PlainTime.of(24));
ClockInterval slot = ClockInterval.between(PlainTime.of(13, 0), PlainTime.of(19, 0));
IntervalCollection<PlainTime> icoll = IntervalCollection.onClockAxis().plus(fullDay);
List<ChronoInterval<PlainTime>> result = icoll.minus(slot).getIntervals();
The resulting list of half-open intervals (with open end) can be easily iterated through and gives the expected result {[T00:00/T13:00), [T19:00/T24:00)}. Every result interval can be converted to a standard ClockInterval, too. There are also various methods to print such intervals in a localized way. Furthermore, you might find the class DayPartitionBuilder interesting which allows to connect weekdays and time schedules in streaming, see the example given in the documentation.
About compatibility with java.time:
The between()-methods of ClockInterval also accept instances of java.time.LocalTime.
Every instance of PlainTime can be converted back to LocalTime by help of the method toTemporalAccessor() with the exception of the value 24:00 which exists in Time4J but not in java.time.LocalTime.

Converting ZonedDateTime to string

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.

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