I am dealing with Time and Date in Java.
I am having date as : 2018-08-22T22:00:00-0500
My Time Zone offset here is -0500
How can I get the list of available Time Zone IDs?
My main objective here is to set a date to a particular Time Zone. However I do not know the time zone as it is embedded in this date format.
Update :
My question is different from Java TimeZone offset
as according to the accepted answer to that question, I need to have time zone info : "Europe/Oslo" . However I only have offset. See the accepted answer below which solves my problem.
tl;dr
eachZoneId.getRules().getOffset(
OffsetDateTime.parse(
"2018-08-22T22:00:00-0500" ,
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" )
).toInstant()
).equals( myTargetZoneOffset )
Offset versus Zone
I do not know the time zone as it is embedded in this date format.
No, your input string of 2018-08-22T22:00:00-0500 has no time zone. It has only a mere offset-from-UTC.
An offset is simply a number of hours, minutes, and seconds of displacement ahead of, or behind, UTC. Yours shows an offset five hours behind UTC. In contrast, a time zone is a history of past, present, and future changes to the offset used by the people of a certain region.
OffsetDateTime
In java.time, we represent a moment with an offset as a OffsetDateTime class.
Your input string is in standard ISO 8601 format. So we should be able to parse directly without specifying a formatting pattern, as the java.time classes use ISO 8601 formats by default when parsing/generating strings. However your input lacks a colon in the offset between hours and minutes. While allowed by the standard, the OffsetDateTime class a small bug in Java 8 & 9 that fails by default to parse such values. As a workaround, specify a DateTimeFormatter.
String input = "2018-08-22T22:00:00-0000";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" ); // Specify formatting pattern to match input string.
OffsetDateTime odt = OffsetDateTime.parse( input , f ); // Parse from dumb string to smart `OffsetDateTime` object.
odt.toString(): 2018-08-22T22:00-05:00
Time zone names
How can I get the list of available Time Zone IDs?
Not sure what you mean by “Time Zone IDs”. I am guessing that you are asking for a list of all the time zones using that particular offset-from-UTC at that particular moment.
A proper time zone name has 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(!).
We represent the time zone using the ZoneId. The TimeZone class is now legacy, and should be avoided.
To get our list of ZoneId objects with that offset in use on that date, we need to first extract the offset (ZoneOffset) from our OffsetDateTime.
ZoneOffset offset = odt.getOffset() ;
offset.toString(): -05:00
Next phase is to interrogate all known time zones, asking each for the offset in effect at the moment of our OffsetDateTime. The argument for that moment must be in UTC, a Instant object. So we must extract an Instant from our OffsetDateTime. Still the same moment, the same point on the timeline, but seen through the lens of a different wall-clock time.
Instant instant = odt.toInstant() ; // Extract a UTC value (`Instant`) from our `OffsetDateTime` object.
instant.toString(): 2018-08-23T03:00:00Z
The Z on the end is short for Zulu and means UTC.
Make an empty list to collect the desired zones.
List< ZoneId > hits = new ArrayList<>() ; // Make an empty list of `ZoneId` objects found to have our desired offset-from-UTC.
Now get all known zones. A method exists giving a set of all zone names, but not the zone objects. So for each iteration we must instantiate the ZoneId. Then we ask the zone for its rules, the list of changes in effect over time for that region. To the rules we pass our moment (Instant), and get back the ZoneOffset in effect at that time. If this offset matches our target offset, we add the zone to our list.
Be aware that many of the zones may be essentially duplicates or deprecated. The list of zones has had a fractured history, with many changes, and some are mere aliases to others.
Set < String > names = ZoneId.getAvailableZoneIds(); // Get a collection of all known time zones’ names.
for ( String name : names ) // Loop each name.
{
ZoneId z = ZoneId.of( name ); // Instantiate a `ZoneId` for that zone name.
ZoneRules rules = z.getRules(); // Get the history of past, present, and future changes in offset used by the people of this particular region (time zone).
ZoneOffset o = rules.getOffset( instant ); // Get the offset-from-UTC in effect at this moment for the people of this region.
if( o.equals( offset )) { // Compare this particular offset to see if it is the same number of hours, minutes, and seconds as our target offset.
hits.add( z ); // If we have a hit, add to our collection of `ZoneId` objects.
}
}
Dump our hits collection to the console.
[America/Panama, America/Chicago, America/Eirunepe, Etc/GMT+5, Pacific/Easter, Mexico/General, America/Porto_Acre, America/Guayaquil, America/Rankin_Inlet, US/Central, America/Rainy_River, America/Indiana/Knox, America/North_Dakota/Beulah, America/Monterrey, America/Jamaica, America/Atikokan, America/Coral_Harbour, America/North_Dakota/Center, America/Cayman, America/Indiana/Tell_City, Chile/EasterIsland, America/Mexico_City, America/Matamoros, CST6CDT, America/Knox_IN, America/Bogota, America/Menominee, America/Resolute, SystemV/EST5, Canada/Central, Brazil/Acre, America/Cancun, America/Lima, America/Bahia_Banderas, US/Indiana-Starke, America/Rio_Branco, SystemV/CST6CDT, Jamaica, America/Merida, America/North_Dakota/New_Salem, America/Winnipeg]
Be aware that this list of zones is valid only for our chosen particular moment. In earlier times, or later times, some of these zones may be using some other offset-from-UTC. Conversely, at other moments some zones not on this list may be using our desired offset.
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?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
You can convert your date to a Calendar. Calendar.getTimeZone() would return the TimeZone match the Calendar. And then TimeZone.getAvailableIDs() would give you the available IDs.
Related
I'm working on a project which takes rrule to generate next occurrences. But I'm not able to understand what i need to put in UNTIL tag of rrule.
String str="RRULE:FREQ=MONTHLY;UNTIL=20190625T000000Z;INTERVAL=2;";
Idk how to convert date into "20190625T000000Z".I'm using rfc 2445 java library. If user enters the date as a string for example :25/06/2019......i need to set this value in UNTIL tag as shown above. If I set the default value in UNTIL then it works but not when i make it user friendly.. I'm taking all the values from user as start date, end date, interval, Byday,Until... But idk what value to set in UNTIL.
If someone can help.. Thanks in advance.
Parsing basic ISO 8601 format
Your input 20190625T000000Z is the “basic” variation of standard ISO 8601 format to represent a moment in UTC. The word “basic” means minimizing the use of delimiters (I do not recommend this, as it makes the string less readable by humans).
Defining a formatting pattern to match input.
String input = "20190625T000000Z";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMdd'T'HHmmssX" );
OffsetDateTime odt = OffsetDateTime.parse( input , f );
Dump to console.
System.out.println("odt.toString(): " + odt);
See this code run live at IdeOne.com.
odt.toString(): 2019-06-25T00:00Z
Translating date to moment
If user enters the date as a string for example :25/06/2019......i need to set this value in UNTIL tag as shown above
First, parse that input string into a LocalDate, representing a date-only value, without time-of-day and without time zone.
DateTimeFormatter fDateOnly = DateTimeFormatter.ofPattern( "dd/MM/uuuu" );
LocalDate ld = LocalDate.parse( "25/06/2019" , fDateOnly );
ld.toString(): 2019-06-25
As for translating that date into a moment (a date with time-of-day in a zone or offset-from-UTC), that is trickier than it sounds intuitively.
A date such as the 25th of June 2019 represents an entire day. And a theoretical date at that. The moments when a day begins and ends varies around the globe by time zone. A new day begins much earlier in Tokyo Japan than in Paris France, and even later in Montréal Québec.
Another issue is that the day does not always begin at 00:00:00. Because of anomalies such as Daylight Saving Time (DST), the first moment of a day on some dates in some zones may be something like 01:00:00. Let the java.time classes determine first moment.
ZoneId z = ZoneId.of( "Africa/Tunis" );
ZonedDateTime zdt = ld.atStartOfDay( z );
zdt.toString(): 2019-06-25T00:00+01:00[Africa/Tunis]
That ZonedDateTime object represents a specific moment. But it uses the wall-clock time adopted by the people of a particular region (a time zone). Your goal is a moment in UTC. Fortunately, we can adjust from the zone to UTC by converting to an OffsetDateTime (a date and time with a context of offset-from-UTC rather than a time zone). We can specify UTC (an offset of zero) by the ZoneOffset.UTC constant.
OffsetDateTime odt = zdt.toOffsetDateTime().withOffsetSameInstant( ZoneOffset.UTC );
odt.toString(): 2019-06-24T23:00Z
Note how 00:00 on the 25th in Tunisia is 11 PM “yesterday” the 24th in UTC. Same moment, same simultaneous point on the timeline, but two different wall-clock times.
Lastly, we need a string in that “basic” ISO 8601 format. Use the same formatter we defined above.
DateTimeFormatter fIso8601DateTimeBasic = DateTimeFormatter.ofPattern( "uuuuMMdd'T'HHmmssX" );
String output = odt.format( fIso8601DateTimeBasic );
output: 20190624T230000Z
See this code run live at IdeOne.com.
Just what is the difference between a time zone and an offset-from-UTC? An offset is merely a number of hours-minutes-seconds. Nothing more, nothing less, just a number (well, three numbers). A time zone is much more. A time zone is a history of past, present, and future changes to the offset used by the people of a particular region. For example, in most of North America, the offset changes twice a year, springing ahead an hour and then falling back an hour (the lunacy of Daylight Saving Time (DST)).
Tip: Date-time handling is surprisingly tricky and slippery. If you are working with calendars and the iCalendar spec for data exchange, I suggest you take a long while to study the concepts and practice with the industry-leading java.time classes.
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.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
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?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
I have a date column in postgres db whose value is 2018-11-20 22:07:20. The datatype is timestamz. I want to get the above value in java code and convert that to seconds with respect to the current time. Suppose the current date is 2018-11-21 22:07:20 then the final answer should be 86400 seconds. Can anyone help me with this?
tl;dr
Duration // Represent a span-of-time unattached to the timeline.
.between( // Calculate elapsed time between two moments.
OffsetDateTime.now( ZoneOffset.UTC ) , // Capture the current moment as seen in UTC.
myResultSet.getObject( … , OffsetDateTime.class ) // Retrieve the moment stored in your database as a `OffsetDateTime` object, *not* as a mere string.
) // Return a `Duration` object.
.toSeconds() // View that duration as a total number of whole seconds. Obviously, any fractional second is ignored.
Details
The Answer by Michael is close but not quite correct.
It fails to account for anomalies in your local time zone, such as Daylight Saving Time (DST): LocalDateTime is the wrong class there, as it cannot, by definition, represent a moment.
It also fails to address the bigger problem that dumb strings are being used to exchange date-time values with the database rather than using smart objects.
date column in postgres db whose value is 2018-11-20 22:07:20
No, that is not the value of the column. That is a textual representation of the value. What is the distinction? Well, unfortunately, many tools used to access your data take the liberty of altering the data being retrieved by applying a time zone adjustment.
Even worse, your example text lacks an indicator of time zone or offset-from-UTC. This contradicts your next statement.
The datatype is timestamz.
I think you misspelled timestampz (missing the p). Even so, this seems to be incorrect, as no such type is listed among the Postgres date/time types. Some systems use that word as an abbreviation, but I recommend always using the longer SQL-standard name for clarity.
You likely meant the type TIMESTAMP WITH TIME ZONE which Postgres, like some other databases, stores as a value in UTC. Any indicator of time zone or offset-from-UTC present within incoming data is used to adjust to UTC, then the indicator is discarded. So values going into, and out of, a TIMESTAMP WITH TIME ZONE column in Postgres is always in UTC. Beware, as mentioned above, some tools interfere with the data retrieval by injecting a time zone adjustment, a well-intentioned though very confusing anti-feature.
Smart objects, not dumb strings
As of JDBC 4.2, we can exchange java.time objects with the database via setObject and getObject methods. Use the object rather than mere strings to exchange date-time values.
OffsetDateTime
Retrieve your value from a column of type TIMESTAMP WITH TIME ZONE as an OffsetDateTime value with its offset set to UTC.
OffsetDateTime odtThen = myResultSet.getObject( … , OffsetDateTime.class ) ;
For comparison, get the current moment in UTC. Specify the offset using the constant ZoneOffset.UTC.
OffsetDateTime odtNow = OffsetDateTime.now( ZoneOffset.UTC ) ;
To generate text representing that duration in standard ISO 8601 format, call OffsetDateTime::toString.
Duration
Capture elapsed time as a Duration object.
Duration d = Duration.between( odtNow , odtThen ) ;
To generate text representing that duration in standard ISO 8601 format, call Duration::toString.
String output = d.toString() ; // PnYnMnDTnHnMnS
To see that entire duration as one big count of whole seconds, call Duration::toSeconds.
long secondsElapsed = d.toSeconds() ;
ZonedDateTime
By the way, if you wish to view either the that odtThen or odtNow value through the lens of the wall-clock time used by the people of a particular region (a time zone), apply a ZoneId to get a ZonedDateTime.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-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( "Pacific/Auckland" ) ;
ZonedDateTime zdt = odtThen.atZoneSameInstant( z ) ;
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?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
Parse into a LocalDateTime, then get the Duration between that and the current time, and convert it to seconds.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("your pattern");
LocalDateTime dateTime = LocalDateTime.parse("2018-11-20 22:07:20", formatter);
return Duration.between(dateTime, LocalDateTime.now()).getSeconds();
You can work out the pattern yourself.
I have my app hosted in a London Server. I am in Minasota, USA. So the timezone is different hours.
How can I obtain the current date / time with my time zone. The tricky part is i don't want to fetch current date and time based on server date and time. Is there a way i can fetch the real current date and time based on time zone.
The below code returns information but if the server date is invalid then the response will be invalid date too. But i want the REAL current date and time.
My input will be time zone. Any help is appreciated.
Date date = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// Use Minasota's time zone to format the date in
df.setTimeZone(TimeZone.getTimeZone("America/Minasota"));
System.out.println("Date and time in Minasota: " + df.format(date));
It's important to know that the use of the three letter time-zone abbreviations is deprecated in java 8. So, don't expect them to be supported forever. Here are two equivalent examples of using the java 8 time api to achieve this:
System.out.println(Instant.now().atZone(ZoneId.of("CST",ZoneId.SHORT_IDS)));
System.out.println(Instant.now().atZone(ZoneId.of("America/Chicago")));
This question is possibly a duplicate of this
tl;dr
Is there a way i can fetch the real current date and time based on time zone.
Yes. Use modern java.time rather than terrible legacy classes.
ZonedDateTime.now( // Represent a moment as seen through the wall-clock time used by the people of a particular region (a time zone).
ZoneId.of( "America/Chicago" ) // Specify time zone by proper `Continent/Region` name, *never* 2-4 letter pseudo-zones such as “CST”.
) // Returns a `ZonedDateTime` object.
.toString() // Generate text in standard ISO 8601 format wisely extended to append the name of the time zone in square brackets.
2018-11-07T14:38:24.723394-06:00[America/Chicago]
Details
I have my app hosted in a London Server. I am in Minasota, USA.
This should be irrelevant to your app.
Server should default to UTC time zone (generally).
Client should be asked to confirm their desired/expected time zone (when critical).
Always specify explicitly your desired/expected time zone by passing optional argument rather than relying implicitly on the JVM’s current default time which can change at any moment during runtime(!).
How can I obtain the current date / time with my time zone.
Firstly, most of your business logic, storage, and exchange of date-time values should be done in UTC.
Instant instant = Instant.now() ; // Current moment in UTC.
You can see that same moment through the lens of a wall-clock time used by the people of a particular region, a time zone.
The time zone for Minnesota is America/Chicago.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as CST or EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Chicago" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
As a shortcut, you can skip the Instant.
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
But i want the REAL current date and time
➥ Here is the core concept in mastering date-and-time work: The Instant (UTC) and the ZonedDateTime (some time zone) seen above represent the very same moment. Those two objects represent the same point on the timeline. They are both the “REAL date and time”. They use two different wall-clock times to show the same moment.
If a person in Iceland were on the phone with someone in Minneapolis, and they both look up their respective clocks & calendars on the wall to speak aloud the current date and time, which one of them is correct? Both are correct, two ways to express the same simultaneous moment.
Indeed, you would do well to think of UTC as The One True Time™, with all zoned times as mere variations. Focusing on your own parochial time zone, and then translating back-and-forth, will drive you batty. Focus on UTC, adjust into a time zone only when expected by the user or necessitated by business logic.
This has all been covered many times already on Stack Overflow. So search for more info and examples. And learn to search Stack Overflow before posting.
To generate strings, either call toString for text in standard ISO 8601 format, or use DateTimeFormatter.ofLocalized… to automatically localize, or use DateTimeFormatter.ofPattern to specify a custom formatting pattern. This has been covered many many times on Stack Overflow, so search for more info.
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?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
For a REST web service, I need to return dates (no time) with a time zone.
Apparently there is no such thing as a ZonedDate in Java (only LocalDate and ZonedDateTime), so I'm using ZonedDateTime as a fallback.
When converting those dates to JSON, I use DateTimeFormatter.ISO_OFFSET_DATE to format the date, which works really well:
DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE;
ZonedDateTime dateTime = ZonedDateTime.now();
String formatted = dateTime.format(formatter);
2018-04-19+02:00
However, attempting to parse back such a date with...
ZonedDateTime parsed = ZonedDateTime.parse(formatted, formatter);
... results in an Exception:
java.time.format.DateTimeParseException: Text '2018-04-19+02:00' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {OffsetSeconds=7200},ISO resolved to 2018-04-19 of type java.time.format.Parsed
I also tried ISO_DATE and ran into the same problem.
How can I parse such a zoned date back?
Or is there any other type (within the Java Time API) I'm supposed to use for zoned dates?
The problem is that ZonedDateTime needs all the date and time fields to be built (year, month, day, hour, minute, second, nanosecond), but the formatter ISO_OFFSET_DATE produces a string without the time part.
When parsing it back, there are no time-related fields (hours, minutes, seconds) and you get a DateTimeParseException.
One alternative to parse it is to use a DateTimeFormatterBuilder and define default values for the time fields. As you used atStartOfDay in your answer, I'm assuming you want midnight, so you can do the following:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date and offset
.append(DateTimeFormatter.ISO_OFFSET_DATE)
// default values for hour and minute
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.toFormatter();
ZonedDateTime parsed = ZonedDateTime.parse("2018-04-19+02:00", fmt); // 2018-04-19T00:00+02:00
Your solution also works fine, but the only problem is that you're parsing the input twice (each call to formatter.parse will parse the input again). A better alternative is to use the parse method without a temporal query (parse only once), and then use the parsed object to get the information you need.
DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE;
// parse input
TemporalAccessor parsed = formatter.parse("2018-04-19+02:00");
// get data from the parsed object
LocalDate date = LocalDate.from(parsed);
ZoneId zone = ZoneId.from(parsed);
ZonedDateTime restored = date.atStartOfDay(zone); // 2018-04-19T00:00+02:00
With this solution, the input is parsed only once.
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?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
I found the solution (using TemporalQueries):
parse the date and zone separately, and restore the zoned date using that information:
LocalDate date = formatter.parse(formatted, TemporalQueries.localDate());
ZoneId zone = formatter.parse(formatted, TemporalQueries.zone());
ZonedDateTime restored = date.atStartOfDay(zone);
I just want to share my experience about Java TimeZone. Here was the problem:
The inDaylightTime(Date date) function of timezone always returns 0, regardless of date. Consistently getDSTSavings() also returns 0.
here is the snippet of code to create timezone:
Timezone timezone = TimeZone.getTimeZone("GMT+1:00");
DST in a timezone object created with an id like "UTC+1:00" (or "GMT+1:00") will be different with a timezone object created with corresponding string "Europe/Berlin", so if DST is important to your application, always use full string id's instead of corresponding time offset.
So changing timezone definition to:
Timezone timezone = TimeZone.getTimeZone("Europe/Berlin");
will solve the problem.
No, TimeZone API figures out day light savings. You are using a custom time zone ID.
From the Documentation of TimeZone API
No daylight saving time transition schedule can be specified with a custom time zone ID
So, you need to specify the time zone ID available to get day light savings
Typically, you get a TimeZone using getDefault which creates a TimeZone based on the time zone where the program is running. For example, for a program running in Japan, getDefault creates a TimeZone object based on Japanese Standard Time.You can also get a TimeZone using getTimeZone along with a time zone ID. For instance, the time zone ID for the U.S. Pacific Time zone is "America/Los_Angeles". So, you can get a U.S. Pacific Time TimeZone object with:
Use the time zone ID, this will take care of day light savings in that particular zone
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
tl;dr
Ask if DST is currently in effect.
ZoneId
.of( "Europe/Madrid" )
.getRules()
.isDaylightSavings( Instant.now() )
Ask the offset (hours-minutes-seconds) ahead or behind UTC currently in effect.
ZoneId
.of( "Africa/Tunis" )
.getRules()
.getOffset( Instant.now() )
DST comes and goes
To ask "Is Daylight Saving Time in effect?", you must specify a moment. The very definition of Daylight Saving Time (DST) is that it comes and goes, twice a year.
Use Instant to specify a moment.
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
java.time
You are using terrible date-time classes that are now legacy, supplanted years ago by the modern java.time classes defined in JSR 310.
Use ZoneId rather than TimeZone.
Offset versus time zone
TimeZone.getTimeZone("GMT+1:00");
The string GMT+1:00 does not represent a time zone, it represents an offset. There are many time zones that may all coincidentally be using an offset right now of one hour ahead of UTC, such as Africa/Casablanca, Africa/Brazzaville, Africa/Tunis, Europe/Andorra, Europe/Warsaw, and many more.
Understand that an offset is merely a number of hours-minutes-seconds ahead or behind the prime meridian. An offset looks like +05:30 or -05:00.
A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region. The rules of a time zone are set capriciously by politicians, and change with surprising frequency.
A proper time zone name is composed as Continent/Region such as America/Montreal or America/New_York. See this list of zones at Wikipedia (may not be up-to-date).
ZoneId z = ZoneId.of( "Europe/Gibraltar" ) ;
Asking "Is DST in effect?"
It seems you want to know if DST is currently in effect for a particular time zone. Get the ZoneRules for a particular ZoneId. Then interrogate for a specific moment.
ZoneId z = ZoneId.of( "Europe/Gibraltar" ) ;
ZoneRules rules = z.getRules() ;
boolean dstInEffect = rules.isDaylightSavings( Instant.now() ) ;
And you can ask for the amount of the offset-from-UTC currently in effect. A ZoneOffset object represents that number of hours-minutes-seconds ahead or behind the prime meridian.
ZoneOffset offset = rules.getOffset( Instant.now() ) ;
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.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
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?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….