I'm currently at a loss about the following simple usage of the SimpleDateFormatter:
import java.text.ParseException;
import java.text.SimpleDateFormat;
public static void main(String[] args) throws ParseException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").parse("2018-12-04T22:22:01+1000"));
}
I'm running this example with JDK 1.8.0_192.
My PC is located at CET (+1000), so timezone is equal. So the expected result would be:
Tue Dec 04 22:22:01 CET 2018
But I get the following output:
Tue Dec 04 13:22:01 CET 2018
Does anyone have an Idea what is happening here?
You give it 2018-12-04T22:22:01+1000, which is 2018-12-04T12:22:01 in UTC. While CET is 1 hour ahead UTC, so you get hour 13.
tl;dr
Your original problem was a typo +1000 vs +0100. Nevertheless, all the advice below still applies. You are using terrible old classes that should be avoided.
OffsetDateTime.parse(
"2018-12-04T22:22:01+1000" , // Input in standard ISO 8601, with the COLON omitted from the offset as allowed by the standard but breaking some libraries such as `OffsetDateTime.parse`.
DateTimeFormatter.ofPattern(
"uuuu-MM-dd'T'HH:mm:ssX"
)
) // Returns a `OffsetDateTime` object.
.toInstant() // Adjust into UTC. Returns an `Instant` object. Same moment, different wall-clock time.
.atZone( // Adjust from UTC to some time zone. Same moment, different wall-clock time.
ZoneId.of( "Europe/Brussels" )
) // Returns a `ZonedDateTime` object.
.toString() // Generate text representing this `ZonedDateTime` object in standard ISO 8601 format but wisely extending the standard by appending the name of the time zone in square brackets.
18-12-04T13:22:01+01:00[Europe/Brussels]
Avoid legacy date-time classes
You are using terrible old date-time classes bundled with the earliest versions of Java. Supplanted years ago by the java.time classes.
Use proper time zones
FYI, CET is not a real time zone.
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( "America/Montreal" ) ;
You likely mean a time zone such as Europe/Brussels, Europe/Paris, Europe/Berlin, Africa/Tunis, or Europe/Oslo.
ISO 8601
Your input string 2018-12-04T22:22:01+1000 is in standard format, defined by ISO 8601.
The last part +1000 is an offset-from-UTC, meaning a moment ten hours ahead of UTC. So this value was intended for the wall-clock time used by people is some region in the Pacific, such as time zone Australia/Lindeman.
Do not abbreviate the offset notation
That string +1000 is an abbreviation of an offset, omitting the COLON character delimiter between hours and minutes (and seconds, if any). While the standard allows this omission, I suggest always including the COLON: 2018-12-04T22:22:01+10:00. In my experience, some libraries and protocols break when encountering such strings. And the COLON’s inclusion makes the string more readable for humans.
OffsetDateTime
Indeed, the java.time.OffsetDateTime class meant to parse such standard strings by default has a bug in this regard, failing to parse when the COLON is omitted. Discussed at:
Java 8 Date and Time: parse ISO 8601 string without colon in offset
Cannot parse String in ISO 8601 format, lacking colon in offset, to Java 8 Date
Workaround:
OffsetDateTime odt =
OffsetDateTime.parse(
"2018-12-04T22:22:01+1000" ,
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" )
)
;
See code example running live at IdeOne.com.
odt.toString(): 2018-12-04T22:22:01+10:00
Adjust that value into UTC by extracting an Instant object. Instant is always in UTC by definition.
Instant instant = odt.toString() ;
instant.toString(): 2018-12-04T12:22:01Z
Finally, we can adjust into your own parochial time zone.
By CET I assume you meant a time zone such as Europe/Paris.
ZoneId z = ZoneId.of( "Europe/Paris" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
When calling ZonedDateTime::toString, text is generated in standard ISO 8601 format, but wisely extending the standard to append the name of the time zone in square brackets.
zdt.toString(): 2018-12-04T13:22:01+01:00[Europe/Paris]
All three of these objects (odt, instant, & zdt) refer to the same simultaneous moment, the very same point on the timeline. Their only difference is the wall-clock time. If three people on a conference call in Australia, France, and Iceland (always in UTC) all looked up simultaneously to read the current moment from their respective clock hanging on their local wall, they would read three different values for the same simultaneous moment.
See all this code run live at that IdeOne.com page.
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.
Related
This question already has answers here:
Java Time Zone is messed up
(5 answers)
Closed 3 years ago.
I have a linux machine in UTC timezone.
[user#test packages]$ date +'%:z %Z'
+00:00 UTC
Running cat /etc/localtime also seems to indicate that my machine is in UTC timezone;
[user#test ~]$ cat /etc/localtime
f2UTCTZif2UTC
UTC0
However calling logger.info(new Date()) in a application running tomcat under Java 1.7 returns something like Mon Oct 28 01:51:39 HDT 2019
This is very strange, so I created a simple Java program for testing:
import java.util.Date;
class Test
{
public static void main (String args[])
{
Date dt = new Date();
System.out.println(dt);
}
}
Compile and run it
[user#test]$ /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.211.x86_64/bin/javac Test.java
[user#test]$ /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.211.x86_64/bin/java Test
Mon Oct 28 02:08:49 HDT 2019
My question is why my Linux utility is return date in UTC format, and yet my Java apps are returning dates in HDT format (I don't even know what HDT is).
Since the app I'm maintaining is legacy, I can't use Joda Time or upgrade to Java8 or higher as this would meant lots of code changes.
I finally fix it by doing the following:
Run ln -fs /usr/share/zoneinfo/UTC /etc/timezone and
Modify /etc/sysconfig/clock
I got the idea of looking at /etc/sysconfig/clock after reading this https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6456628
tl;dr
Never use the legacy class Date.
Instant.now()For current moment as seen in UTC.
ZonedDateTime.now( ZoneId.of( "Pacific/Honolulu" ) )For current moment as seen in a particular time zone.
2020-02-18T05:28:11.146726Z
2020-02-17T19:28:11.146726-10:00[Pacific/Honolulu]
Details
Firstly, you should know that your java.util.Date is actually a moment in UTC but its toString method dynamically applies the JVM's current default time zone while generating the text. Very confusing. One of many reasons to never use this class.
Date, Calendar, and the other legacy date-time classes were supplanted by java.time years ago with the adoption of JSR 310.
Avoid depending on default time zone
Using the java.time classes, you can easily write code that does not depend on a default time zone. You can specify your desired offset-from-UTC or time zone explicitly, whether that be UTC itself (an offset of zero hours-minutes-seconds) or a time zone like Pacific/Honolulu.
UTC
If you want to track a moment in UTC, use Instant.
Instant instant = Instant.now() ;
The Instant::toString method generates text in standard ISO 8601 format. The formats defined by this standard are designed for data exchange.
String output = instant.toString() ;
output: 2020-02-18T05:28:11.146726Z
The Z on the end means UTC, and is pronounced “Zulu”.
Zoned
If you want to see that same moment by the wall-clock time used by the people in Hawaii, apply a ZoneId to get a ZonedDateTime.
Never use the 2-4 letter abbreviation such as HDT or EST or IST as they are not true time zones, not standardized, and not even unique(!).
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland.
ZoneId z = ZoneId.of( "Pacific/Honolulu" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
The ZonedDateTime::toString method wisely extends the ISO 8601 format by appending the name of the time zone is square brackets.
String output = zdt.toString() ;
See this code run live at IdeOne.com.
outputZdt: 2020-02-17T19:28:11.146726-10:00[Pacific/Honolulu]
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….
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 am very new to OffsetDateTime usage and I am trying to compare OffsetDateTime strings with OffsetDateTime.now() in java this way,
import java.time.OffsetDateTime;
public class OffsetDateTimeDemo {
public static void main(String[] args) {
OffsetDateTime one = OffsetDateTime.parse("2017-02-03T12:30:30+01:00");
System.out.println("First ::" + OffsetDateTime.now().compareTo(one));
OffsetDateTime date1 = OffsetDateTime.parse("2019-02-14T00:00:00");
System.out.println("Second ::" + OffsetDateTime.now().compareTo(date1));
OffsetDateTime date3 = OffsetDateTime.parse("Mon Jun 18 00:00:00 IST 2012");
System.out.println(" Third :: " +OffsetDateTime.now().compareTo(date3));
}
}
But I am getting java.time.format.DateTimeParseException in all the 3 cases.
However if i compare 2 OffsetDateTime Strings with CompareTo method its working fine.
Can someone shed some light to me in this regard and kindly guide me through my mistake.
Thanks in Advance.
Your compareTo coding is a distraction. Your exception is about parsing the string inputs into objects.
Another problem: You are using wrong classes on the 2nd and 3rd inputs.
Another problem: You are relying implicitly on your JVM’s current default time zone when calling now(). Poor practice as any programmer reading will not know if you intended the default or if you were unaware of the issue as are so many programmers. Furthermore, the current default can be changed at any moment during runtime by any code in any thread of any app within the JVM. So better to always specify explicitly your desired/expected zone or offset.
OffsetDateTime.now(
ZoneOffset.UTC
)
Or better yet, use a ZonedDateTime to capture more information than a OffsetDateTime.
ZonedDateTime.now(
ZoneId.of( "Pacific/Auckland" )
)
First: OffsetDateTime works
Your first string input is proper, and parses successfully.
OffsetDateTime.parse( "2017-02-03T12:30:30+01:00" )
Full line of code:
OffsetDateTime odt = OffsetDateTime.parse( "2017-02-03T12:30:30+01:00" ) ;
See this code run live at IdeOne.com.
odt.toString(): 2017-02-03T12:30:30+01:00
To compare, extract an Instant. Doing so effectively adjusts your moment from some offset to an offset of zero, or UTC itself. An Instant is always in UTC, by definition.
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
boolean odtIsPast = odt.toInstant().isBefore( instant ) ;
Second: LocalDateTime
Your second string input lacks any indicator of offset-from-UTC or time zone. So an OffsetDateTime is the wrong class to use. Instead use LocalDateTime which lacks any concept of offset or zone.
This means a LocalDateTime cannot represent a moment. For example, noon on the 23rd of January this year could mean noon on Asia/Tokyo which would be hours earlier than noon in Europe/Paris, or it could mean noon in America/Montreal which would be a moment even more hours later. Without the context of a zone or offset, a LocalDateTime has no real meaning. So comparing a LocalDateTime to the current moment is senseless.
LocalDateTime.parse( "2019-02-14T00:00:00" )
See this code run live at IdeOne.com.
ldt.toString(): 2019-02-14T00:00
To compare, you can’t — illogical as discussed above. You must assign a time zone (or offset) to determine a moment on the timeline. If you know for certain this date and time were meant for a specific time zone, assign ZoneId to get a ZonedDateTime. Then extract a Instant to compare.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ; // India time.
ZonedDateTime zdt = ldt.atZone( z ) ;
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
boolean zdtIsPast = zdt.toInstant().isBefore( instant ) ; // Compare.
By the way, I noticed the time-of-day is zero. If your goal was to represent the date only, without any time-of-day and without any zone, use LocalDate class.
Third: Don’t bother, ambiguous input
Your third string input carries a time zone indicator. So it should be parsed as a ZonedDateTime.
Unfortunately, you’ve chosen a terrible string format to parse. Never use the 2-4 character pseudo-zones like IST. They are not standardized. And they are not unique! Your IST could mean Ireland Standard Time or India Standard Time or others.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
See this code run live at IdeOne.com.
zdt.toString(): 2019-02-20T22:34:26.833+01:00[Africa/Tunis]
You could try to parse this. ZonedDateTime will make a guess as to which zone was meant by IST. But it would be just a guess, and so is unreliable given the inherently ambiguous input. Personally, I would refuse to code that, rejecting this input data back to its source.
If you insist on making this unreliable parse attempt, see the correct Answer to a similar Question you asked recently.
Educate your source about always using standard ISO 8601 formats to exchange date-time values as human-readable text.
The java.time classes use these ISO 8601 formats by default when parsing/generating strings. The ZonedDateTime class wisely extends the standard to append the standard name of the time zone in square brackets.
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.
Following is the code snippet which is throwing an exception:
SimpleDateformat dateFormatter = new SimpleDateFormat("yyyyMMddHHmm");
Date date = dateFormatter.parse("201710010200");
The code above threw exception for all the dates after 2:00 A.M. It ran well till 01:30 A.M.
DayLight saving time was configured (I'm using Australia/Sydney timezone).
After that, I could see logs of 3:00 A.M.
Time between 2:00 A.M. and 3:00 A.M. is not logged too.
Log:
01 Oct 03:02:01 ERROR : Unparseable date: "201710010200"
Caused by: java.text.ParseException: Unparseable date: "201710010200"
at java.text.DateFormat.parse(DateFormat.java:357)
What could be the fix of the problem of the date string "201710010200" not getting parsed, with the right date format specified?
You're trying to parse a date/time that didn't occur.
We now know that this was in the Sydney time zone. At 2am on October 1st 2017 in Sydney, the clocks went forward to 3am. If you were looking at a clock every minute you'd see:
01:58
01:59
03:00
03:01
So any date/time between 2am (inclusive) and 3am (exclusive) simply didn't occur in that time zone. We don't know what produced the values you're trying to parse, but:
If they're timestamps, it would almost certainly be better to both format and parse in UTC. Keep an offset from UTC and potentially a time zone ID if the time zone in which they were produced is important for future analysis.
If they're date/time values which aren't linked to any particular time zone, don't parse them as if they were in a time zone. Ideally, use Java 8's java.time package and parse them as LocalDateTime values
tl;dr
LocalDateTime.parse( // Parse a string lacking any indicator of time zone or offset-from-UTC into a `LocalDateTime` object.
"201710010200" , // Parse string in “basic” ISO 8601 format.
DateTimeFormatter.ofPattern( "uuuuMMddHHmm" ) // Define a formatting pattern to match the input. If you used expanded ISO 8601 format instead of “basic” you would not need to bother with this step.
).atZone( // Place the inexact unzoned value (`LocalDateTime` object) into the context of a time zone. Produces a `ZonedDateTime` object.
ZoneId.of( "Australia/Sydney" )
).toString() // Generate a string in standard expanded ISO 8601 format. This class extends the standard to wisely append the name of the zone in square brackets.
2017-10-01T03:00+11:00[Australia/Sydney]
If that time-of-day on that date in than zone is invalid, ZonedDateTime class adjusts.
If you fear faulty input, trap for DateTimeParseException.
Details
The Answer by Jon Skeet is correct. Per his comment: There is no instant in time which had a local time of 2am on October 1st 2017 in Sydney.
java.time
The modern solution is the java.time classes that supplant the troublesome old legacy date-time classes.
Parsing
Define a formatting pattern to match your input.
String input = "201710010200" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMddHHmm" ) ;
LocalDateTime
Your input lacks an indicator of offset-from-UTC or time zone. So parse as a LocalDateTime.
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
ldt.toString(): 2017-10-01T02:00
Without the context of a time zone or offset-from-UTC, this value has no real meaning. It does not represent a moment, a point on the timeline. It is only a vague idea about possible moments over a range of about 26-27 hours.
To determine a moment, we need to place this value within the context of a time zone or offset.
You claim to know that value was intended to represent a moment in Australia/Sydney time zone.
ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
2017-10-01T03:00+11:00[Australia/Sydney]
The result is 3 AM. The offset-from-UTC used by the people of that region changed on that date at that time, a cut-over in Daylight Saving Time (DST) silliness. When the clock in that part of Australia was about to strike 2 AM, the clock jumped to 3 AM. The 2 AM hour never existed in that land. The ZonedDateTime class has a policy for automatically adjusting such invalid moment. Be sure to read the doc to see if you understand enter link description hereand agree with its algorithm.
Because this wall-clock time never existed, I suspect you are incorrect about that log data representing a moment in the zone of Australia/Sydney.
UTC
The bigger solution here is to learn to think, work, log, and exchange data all in UTC. Consider UTC to be the One True Time, and all other zones are but a mere variation of that theme. Forget about your own parochial time zone while at work programming/administrating.
In java.time, the basic class for UTC values is Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
This class can capture the current moment in UTC.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
ISO 8601
The Instant class also can parse/generate strings in standard ISO 8601 format.
String output = Instant.now().toString() ;
"2018-01-23T12:34:56.734591Z"
The Z on the end is short for Zulu and means UTC. This is the crux of your original problem: You stored date-time values without such an indicator of zone/offset.
Parsing:
Instant instant = Instant.parse( "2018-01-23T12:34:56.734591Z" )
I strongly recommending using the ISO 8601 formats for all such storage/exchange of textual date-time values. Be sure to:
include offset/zone when storing/exchanging moments, precise points on the timeline.
Use expanded formats, rather than these “basic” formats that minimize the use of delimiters. These are hard to read by humans, less obvious as to the type of information, and are not used by default in java.time. The java.time classes use the expanded formats by default.
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.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor 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.
I am in MST and I want my Date in PST. I set the timeZone that I want.
Now if i do c.getTime() I always get my server time.
Instead I want Pacific Date time. Please help
How to get the date time Object in the specified timezone.
Calendar c= Calendar.getInstance();
TimeZone timezone= TimeZone.getTimeZone("PST");
c.setTimeZone(timezone)
Or, use JodaTime
#Grab( 'joda-time:joda-time:2.3' )
import org.joda.time.*
def now = new DateTime()
println now.withZone( DateTimeZone.forTimeZone( TimeZone.getTimeZone( "PST" ) ) )
TimeZone.setDefault(TimeZone.getTimeZone('PST'))
println new Date() //PST time
You can set the default timezone to PST/MST according to your need and then get the date. I would do this in a test method, if possible.
UPDATE: The Joda-Time project has been succeeded by the java.time classes. See this other Answer.
(a) Use Joda-Time (or new JSR 310 built into Java 8). Don't even think about using the notoriously bad java.util.Date/Calendar.
(b) Your question is not clear. Your comments on answers talk about comparing, but you say nothing about comparing in your question.
(c) Avoid the use of 3-letter time zone abbreviations. Read note of deprecation in Joda-Time doc for TimeZone class.
(d) Avoid default time zone. Say what you mean. The time zone of your computer can change intentionally or not.
(e) Search StackOverflow for 'joda' for lots of code snippets and examples.
(f) Here's some Joda-Time example code to get you started.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// Specify your time zone rather than rely on default.
org.joda.time.DateTimeZone californiaTimeZone = org.joda.time.DateTimeZone.forID( "America/Los_Angeles" );
org.joda.time.DateTimeZone denverTimeZone = org.joda.time.DateTimeZone.forID( "America/Denver" );
org.joda.time.DateTime nowDenver = new org.joda.time.DateTime( denverTimeZone );
org.joda.time.DateTime nowCalifornia = nowDenver.toDateTime( californiaTimeZone );
// Same moment in the Universe’s timeline, but presented in the local context.
System.out.println( "nowDenver: " + nowDenver );
System.out.println( "nowCalifornia: " + nowCalifornia );
When run…
nowDenver: 2013-11-21T18:12:49.372-07:00
nowCalifornia: 2013-11-21T17:12:49.372-08:00
About Joda-Time…
// Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
// http://www.joda.org/joda-time/
// Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
// JSR 310 was inspired by Joda-Time but is not directly based on it.
// http://jcp.org/en/jsr/detail?id=310
// By default, Joda-Time produces strings in the standard ISO 8601 format.
// https://en.wikipedia.org/wiki/ISO_8601
// About Daylight Saving Time (DST): https://en.wikipedia.org/wiki/Daylight_saving_time
// Time Zone list: http://joda-time.sourceforge.net/timezones.html
tl;dr
ZonedDateTime
.now(
ZoneId.of( "America/Los_Angeles" )
)
See this code run live at IdeOne.com. (Be aware the system clock on that site seems to be about a half-hour slow today.)
zdt.toString(): 2019-07-27T12:29:42.029531-07:00[America/Los_Angeles]
java.time
The modern approach uses the java.time classes built into Java 8 and later, defined in JSR 310.
I am in MST and I want my Date in PST. I set the timeZone that I want.
Never depend on the current default time zone of the JVM at runtime. As a programmer, you have no control over that default. So the results of your code may vary unexpectedly.
Always specify the optional time zone arguments to date-time methods.
Now if i do c.getTime() I always get my server time.
Learn to think not of client-time or server-time, but rather UTC. Most of your business logic, data storage, data exchange, and logging should be done in UTC. Think of UTC as the One True Time™, and all other offsets/zones are but mere variations.
For UTC, use Instant.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
Generate text representing that moment in standard ISO 8601 format.
String output = instant.toString() ;
Instead I want Pacific Date time. Please help How to get the date time Object in the specified timezone.
None of your terms (Pacific, MST, or PST) are true time zones.
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( "America/Montreal" ) ;
To adjust from UTC to a time zone, apply a ZoneId to get a ZonedDateTime.
ZoneId z = ZoneId.of( "America/Edmonton" ) ; // https://time.is/Edmonton
ZonedDateTime zdt = instant.atZone( z ) ;
And try one of the time zones on the west coast of North America.
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ; // https://time.is/Los_Angeles
ZonedDateTime zdt = instant.atZone( z ) ;
To generate strings in formats other than ISO 8601, use the DateTimeFormatter class. Search Stack Overflow as this has been covered many many times already.
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.
The Java Date object do not have a timezone -- it just represents a point in time.
If you would like to format a date into a timezone, you can set it in the DateFormat class. For example:
Date date = new Date ();
DateFormat df = DateFormat.getDateTimeInstance();
df.setTimeZone(TimeZone.getTimeZone("PST"));
System.out.println(df.format(date));
df.setTimeZone(TimeZone.getTimeZone("EST"));
System.out.println(df.format(date));
will display a time in PST, then a time in EST.
I had to a similar issue myself recently, and setting the timezone to a locale worked better for me (i.e. not EST/EDT, but America/New_York). I tried EST then tried to do the daylight savings time offset stuff for EDT and this turned out to be a heck of lot easier. Set your timezone to whatever you want it to be then make use of the Date object to create a new date and it will for that timezone. Then you can use the format method to take a timestamp however you please.
TimeZone.setDefault(TimeZone.getTimeZone("America/New_York"));
Date date = new Date();
timeStamp = date.format('yyyy-MM-dd HH:mm:ss.SSSZ');
System.out.println(timeStamp);
Returns
"2019-07-25 17:09:23:626-0400"