tl;dr
Use a time zone (continent/region
) rather than a mere offset-from-UTC (hours-minutes-seconds). For any particular zone, the offset is likely to change over time.
Combine the two to determine a moment.
LocalDate.parse(
"2018-04-19"
)
.atStartOfDay(
ZoneId.of( "Europe/Zurich" )
) // Returns a `ZonedDateTime` object.
2018-04-19T00:00+02:00[Europe/Zurich]
From your REST service, either:
- Return the date and zone separately (either with a delimiter or as XML/JSON), or,
- Return the start of day as that is likely the intended outcome of a date with a time zone.
Separate your text inputs
The solution in the Answer by Walser is effectively treating the string input as a pair of string inputs. First the date-only part is extracted and parsed. Second, the offset-from-UTC part is extracted and parsed. So, the input is parsed twice, each time ignoring the opposite half of the string.
I suggest you make this practice explicit. Track the date as one piece of text, track the offset (or, better, a time zone) as another piece of text. As the code in that other Answer demonstrates, there is no real meaning to a date with zone until you take the next step of determining an actual moment such as the start of day.
String inputDate = "2018-04-19" ;
LocalDate ld = LocalDate.parse( inputDate ) ;
String inputOffset = "+02:00" ;
ZoneOffset offset = ZoneOffset.of( inputOffset) ;
OffsetTime ot = OffsetTime.of( LocalTime.MIN , offset ) ;
OffsetDateTime odt = ld.atTime( ot ) ; // Use `OffsetDateTime` & `ZoneOffset` when given a offset-from-UTC. Use `ZonedDateTime` and `ZoneId` when given a time zone rather than a mere offset.
odt.toString(): 2018-04-19T00:00+02:00
As you can see, the code is simple, and your intent is obvious.
And no need to bother with any DateTimeFormatter
object nor formatting patterns. Those inputs conform with ISO 8601 standard formats. The java.time classes use those standard formats by default when parsing/generating strings.
Offset versus Zone
As for applying the date and offset to get a moment, you are conflating a offset-from-UTC with a time zone. An offset is simply a number of hours, minutes, and seconds. No more, no less. In contrast, a time zone is a history of the past, present, and future changes in offset used by the people of a particular region.
In other words, the +02:00
happens to be used by many time zones on many dates. But in a particular zone, such as Europe/Zurich
, other offsets may be used on other dates. For example, adopting the silliness of Daylight Saving Time (DST) means a zone will be spending half the year with one offset and the other half with a different offset.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Europe/Zurich" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;
zdt.toString(): 2018-04-19T00:00+02:00[Europe/Zurich]
So I suggest you track two strings of input:
- Date-only (
LocalDate
): YYYY-MM-DD such as 2018-04-19
- Proper time zone name (
ZoneId
): continent/region such as Europe/Zurich
Combine.
ZonedDateTime zdt =
LocalDate.parse( inputDate )
.atStartOfDay( ZoneId.of( inputZone ) )
;
Note: The ZonedDateTime::toString
method generates a String in a format that wisely extends the standard ISO 8601 format by appending the name of the time zone in square brackets. This rectifies a huge oversight made by the otherwise well-designed standard. But you can only return such a string by your REST service if you know your clients can consume it.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.