DST changes caused an java.text.ParseException: Unparseable date - java

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.

Related

Rrule Until tag data value

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.

SimpleDateFormat - Strange result when parsing Date

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.

How to fetch correct date and time without server time in java with time zone as input

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.

Simple Java String to java.util.Date conversion adds unwanted daylight saving

This is my program snippet
import java.lang.Math;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class Main
{
public static void main(String[] args)
{
String dateTime = "2017-03-12 02:46:00";
// convert string to java.util.Date
try {
SimpleDateFormat e = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = e.parse(dateTime);
System.out.println(d);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
This is the output of that program
Sun Mar 12 03:46:00 PDT 2017
Expected Output
Sun Mar 12 02:46:00 PDT/PST 2017
Apparently, it is adding daylight saving time which occurs on PST at 2017-03-12 02:00:00
Few things I am bounded.
I cannot change server default timezone or anything specific to JVM
I must return back java.util.Date as final value.
Edit:
To some comment pointing me out how java.util.Date only stores long timestamp. Can you please give me a way where this function works
java.util.Date convertStringToDate(String str) {
// code to convert String to Date
}
convertStringToDate("2017-03-12 02:46:00");
should give me 2017-03-12 02:46:00 value in Date class? I don't care about what timezone it provides. It should have that value, whatever timezone it is while printing. Again my JVM is in PST.
Use java.time, not legacy date-time classes
You are using troublesome old date-time classes such as java.util.Date that are now legacy, supplanted by the java.time classes.
LocalDateTime
2016-03-12 02:46:00 value …I don't care about what timezone it provides. It should have that value, whatever timezone it is…
If you truly want to represent that date and time-of-day without regard for time zone, use the LocalDateTime class. This class purposely ignores time zone.
To parse, adjust your input string to comply with the ISO 8601 standard formats used by the java.time classes for parsing/generating strings.
String input = "2016-03-12 02:46:00".replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( input );
But beware: By ignoring time zone you lose the meaning of this date+time. Without the context of a time zone, we do not know if you mean the 2 AM in Auckland NZ, or 2 AM in Kolkata India (some hours later), or 2 AM in Paris France (more hours later), or 2 AM in Montréal Québec (still more hours later). A LocalDateTime is a rough idea about possible moments, but is not actually a point on the timeline.
ZonedDateTime
This is the output of that program Sun Mar 12 03:46:00 PDT 2017
Expected Output Sun Mar 12 02:46:00 PDT/PST 2017
Now you contradict yourself.
By including the PDT or PST with your expected output, you mean a specific moment on the timeline perceived through the lens of a particular region’s wall-clock time. This contradicts your statement that you want "2016-03-12 02:46:00" regardless of time zone. It is crucial that you understand this distinction to properly handle date-time work.
If indeed the intent of the string 2016-03-12 02:46:00 is to represent a moment in the wall-clock time of the left coast of north America (as I guess you meant by PDT), then we must parse that string firstly as a LocalDateTime as it lacks any indicator of time zone, but then immediately adjust it into a time zone to get a ZonedDateTime object.
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 or PDT or PST as they are not true time zones, not standardized, and not even unique(!).
Here I arbitrarily chose America/Los_Angeles as the time zone, as your Question does not mention a specific time zone, only “PDT”.
String input = "2017-03-12 02:46:00".replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( input );
ZoneId z = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = ldt.atZone( z );
But it just so happens that March 12 of 2017 has an anomaly. That is the day when the craziness known as Daylight Saving Time (DST) kicks in. The clocks in much of the left coast of north America at 2 AM jump to 3 AM. There is no two o’clock hour. The day is 23 hours long rather than the usual 24 hours. So your request for 2:46 is asking for a nonexistent moment, an invalid value. The design choice in java.time to resolve this conundrum is to jump forward, following the "Spring Forward" of DST. The result is in the 3 AM hour, 03:46.
See this code run live in IdeOne.com.
input: 2017-03-12T02:46:00
ldt.toString(): 2017-03-12T02:46
zdt.toString(): 2017-03-12T03:46-07:00[America/Los_Angeles]
Note the 2 AM hour becomes the 3 AM hour in that output.
A reasonable person could make arguments for a different design choice in handling this anomaly, such as throwing an Exception. But this is how java.time works. Study the class doc and be sure you understand the behavior on this important topic.
If you want to detect such an anomaly, call toLocalDateTime on the ZonedDateTime object, and compare to the first LocalDateTime. With no anomaly, the pair of LocalDateTime objects will be equal; with an anomaly they will not be equal.
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.
Where to obtain the java.time classes?
Java SE 8 and 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 SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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.

How to display time like hours:minutes:seconds:milliseconds:microseconds?

Is there any way to display time upto microseconds precision using LocalDateTime in java? Like we used in SimpleDateFormat:
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:S");
Similarly, what should I do if I want to display like this: hours:minutes:seconds:milliseconds:microseconds
I read it can be done using LocalDateTime. But how?
ISO 8601
Your desired format for a time-of-day is standard ISO 8601 format. The java.time classes use ISO 8601 formats by default when parsing/generating String representations of their date-time values.
Nanoseconds
The java.time classes support a resolution up to nanoseconds. The legacy date-time classes they supplant were limited to milliseconds.
LocalTime
The LocalTime class represents a time-of-day without a date and without a time zone.
Determining the current time-of-day does require a time zone. For any given moment, the time-of-day varies around the globe by zone.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalTime lt = LocalTime.now( z );
Generate a String by calling toString.
String output = lt.toString(); // 12:34:56.789
In Java 8, capturing the current time is limited to milliseconds. The class can hold up to nanoseconds, but the Clock implementation has legacy limitations. In Java 9, a new Clock implementation is capable of capturing the current time in up to nanoseconds (depending on the host computer’s hardware capability).
The Question mentions LocalDateTime. That class is for a date-time, a date plus a time-of-day. But the class purposely lacks any concept of time zone. Almost never what you want, as a LocalDateTime does not represent a moment on the timeline. Without the context of a time zone saying "3 PM on Jan 15th this year" has no meaning as 3 PM in Paris Texas is not the same as in Montréal Québec which is not the same as in Auckland New Zealand. Assign a time zone (ZoneId) to determine an actual moment in a ZonedDateTime object. For UTC values, just use Instant.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
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.
Looks like java.time.format.DateTimeFormatter will do you what you want. See the javadoc here: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
The codes appear to be the same as they were with SimpleDateFormat, so the same format string "HH:mm:ss:S" will continue to work.
Last I read, java 8 can do nanoseconds as per documentation here... https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html - I heard java 9 will have some major updates to date and time features.
Java7
If you use a Timestamp Object then you can use the normal formatting for the Date part and then append ":" + timestamp.getNanos (); to get a nano second formatting String

Categories