Reputation: 32966
We have a library used for generating reports. It reads from a data file (SQL, XML, JSON, etc.), the datetime may then be modified in a user written equation, and then it is formatted as specified for the report output.
The use in an equation can be add a timespan, get parts of the value as in "if date.month == 2", and pretty much all the datetime macros in Excel.
Because the data can be JSON (or XML with no schema) the datetime can be "2019-01-25", "2019-01-25T14:32:23", "2019-01-25T14:32:23.12345", "2019-01-25T14:32:23Z", or "2019-01-25T14:32:23Z-0500" (last two can have the ".12345" also).
If there's no timezone offset we assume the datetime is UTC. While that should be true, often it isn't and it's local time but the way it's used, it doesn't matter. So making it UTC unless a timezone offset is specified works (up till now we've used Date).
First question - what class should I use to hold this value? From what I've read I think ZonedDateTime, but maybe Instant?
Second question - what class should I use for timespan when I have to do something like add 3 days to the datetime?
Third question - is there some parser that can parse all the different strings as I listed above? Or do I need to call String.contains() to determine the format and then do an explicit pattern based on that? And if so, using what class?
Upvotes: 9
Views: 4107
Reputation: 11739
Third question - is there some parser that can parse all the different strings as I listed above? Or do I need to call String.contains() to determine the format and then do an explicit pattern based on that? And if so, using what class?
I might be horrible wrong, but can you use DateTimeFormatter
with optional parts on pattern and parseBest method:
List<String> dates = List.of(
"2019-01-25",
"2019-01-25T14:32:23",
"2019-01-25T14:32:23.12345",
"2019-01-25T14:32:23Z",
"2019-01-25T14:32:23Z-0500"
);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"yyyy-MM-dd['T'[HH:mm:ss][.SSSSS]][z][x]"
); // all the possible combinations
dates.forEach( date -> {
TemporalAccessor accessor = formatter.parseBest(date,
OffsetDateTime::from, // going from most specific date
LocalDateTime::from,
LocalDate::from); // to the less specific
System.out.println( accessor.getClass() + " " + accessor);
}
);
// output for this is
class java.time.LocalDate 2019-01-25
class java.time.LocalDateTime 2019-01-25T14:32:23
class java.time.LocalDateTime 2019-01-25T14:32:23.123450
class java.time.OffsetDateTime 2019-01-25T14:32:23Z
class java.time.OffsetDateTime 2019-01-25T14:32:23-05:00
Upvotes: 6
Reputation: 14373
As to the 2nd question: Yes there is a "timespan" class in the Java JDK.
For a span-of-time not attached to the timeline:
Period
Represents a number of days/weeks/months/years. Can be used in date calculations, automatically accounting for Daylight Savings Time (DST).
For example, to subtract 3 days from a given date, you could do
ZonedDateTime threeDaysAgo = Period.ofDays(-3).addTo(ZonedDateTime.now());
Duration
Similar to Period
but on the scale of days (as 24-hour chunks, not calendar days), hours, minutes, seconds, and fractional second.
ChronoUnit
If you need to do calculations on a wider scale (like include hours/minutes/secods etc) There is also the ChronoUnit
enum:
ZonedDateTime threeHoursAgo = ChronoUnit.HOURS.addTo(ZonedDateTime.now(), -3);
Upvotes: 3