How to convert json date to java.util.Date
{"date":31,"day":4,"hours":0,"minutes":0,"month":11,"seconds":0,"time":2145805200000,"timezoneOffset":-420,"year":137}
Thanks for help
With a quick Google search, I managed to find this webpage: CLICK
The 'parse' method returning a Date shows you how to use the SimpleDateFormat class in Java which is used to parse a String into a Date.Hope this helped!
No JSON Date
No such thing as a JSON date. JSON has very few data types, none of which are date-time related.
Count Since Epoch
That time item with value 2145805200000 is probably a count since epoch. The two questions are: What epoch? and What granularity of count?
Commonly used are milliseconds since the Unix epoch of first moment of 1970 in UTC.
The java.time framework built into Java 8 and later can translate such number. The Instant class represents a moment on the timeline in UTC.
long sinceEpoch = 2145805200000L;
Instant instant = Instant.ofEpochMilli ( sinceEpoch );
Dump to console.
System.out.println ( "instant: " + instant );
instant: 2037-12-30T17:00:00Z
That value may be close to the other fields in your JSON, but is not quite a match.
Your JSON has an field timezoneOffset with value -420. If we interpret that number as an offset-from-UTC in minutes, that would mean 7 hours. We can ask java.time to adjust the Instant into such an offset.
Normally we would want to use a time zone for this adjustment. A time zone is an offset-from-UTC plus a set of historic rules for handling anomalies such as Daylight Saving Time (DST). But in this case we have only the offset-from-UTC. So rather than use a ZoneId we use the subclass ZoneOffset. The result is a ZonedDateTime.
ZoneOffset zoneOffset = ZoneOffset.ofHours ( 7 );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneOffset );
Dump to console.
System.out.println ( "instant: " + instant + " + zoneOffset: " + zoneOffset + " = zdt: " + zdt );
instant: 2037-12-30T17:00:00Z + zoneOffset: +07:00 = zdt: 2037-12-31T00:00+07:00
That gets us to the beginning of the day on the 31st of December in 2037. Still not an exact match to the other JSON fields.
But if that -420 was meant as being 7 hours behind UTC rather than ahead, we need to change that offset from 7 hours to a negative -7 hours. Then the results would be:
instant: 2037-12-30T17:00:00Z + zoneOffset: -07:00 = zdt: 2037-12-30T10:00-07:00
If you knew more about your JSON data, then perhaps a solution could be found.
Related
I'm developing a Java API that is being used by an android app. I have arrived to a point where I need to correctly handle date and time taking into account timezones.
One of the features of the app is to book some sort of service specifying a date and a time. There is the possibility for the user to cancel the booking and if the cancellation occurs 24h before the booking starts, the client gets all the amount refunded.
Now let's say the server is in London(gmt 0) and the user in Spain(gmt +1) and a booking start on 25-02-2015 at 16:00:00.
When the user cancels a booking the server needs to make the difference between NOW() and the booking start date. So if the user (in spain) makes a cancelation the 24-02-2015 at 17:00:00(spain time, 23hours before booking ; therefore he doesn't get full refund)
when the server checks the difference, because the NOW (it is 16:00:00 in UK) the result will be 24h and therefore will refund full amount wrongly.
My question is here. How do I correctly get the RIGHT amount of hours depending on the user timezone ?
I'm not very happy with sending the client time zone in the cancellation request because the value can easily be tricked by the user.
What is a good practice when storing date and time sever side ? Should I store them in the server time and use an extra field to know the client timezone offset's ?
The Answer by Baranauskas is correct.
Work in UTC
Generally all your business logic, data exchange, data storage, and serialization, should be done in UTC. Apply a time zone only where required/expected, such as presentation to a user.
java.time
Definitely use java.time framework built into Java 8 and later.
By default, the java.time classes use standard ISO 8601 formats for parsing/generating textual representations of date-time values. Otherwise use a DateTimeFormatter object.
The Local… types are generic, not applying to any locality, having no time zone or offset-from-UTC. Generally not used in business apps as they are not actual moments on the timeline. Used here for parsing a date string and a time string separately, combining, and then applying the known time zone for Spain. Doing so produces a ZonedDateTime, an actual moment on the timeline.
LocalDate dateBooking = LocalDate.parse ( "2016-02-25" ); // Parses strings in standard ISO 8601 format.
LocalTime timeBooking = LocalTime.parse ( "16:00:00" );
LocalDateTime localBooking = LocalDateTime.of ( dateBooking , timeBooking );
ZoneId zoneId = ZoneId.of ( "Europe/Madrid" );
ZonedDateTime zonedBooking = localBooking.atZone ( zoneId );
From that we can extract an Instant, a moment on the timeline in UTC.
Instant booking = zonedBooking.toInstant ();
Calculate our 24 hours of required notice for cancellations. Note that 24-hours is not the same as “one day” as days vary in length because of anomalies such as Daylight Saving Time (DST).
Instant twentyFourHoursEarlier = booking.minus ( 24 , ChronoUnit.HOURS );
Get the current moment for the user in process of cancelling. Here we simulate by using the date-time specified in the Question. For shorter code, we adjust by an hour because this parse method handles only UTC (Z) strings. The Question stated 17:00 in Spain time; Europe/Madrid is one hour ahead of UTC so we subtract an hour for 16:00Z.
Instant cancellation = Instant.parse ( "2016-02-24T16:00:00Z" ); // 17:00 in Europe/Madrid is 16:00Z.
// Instant cancellation = Instant.now (); // Use this in real code.
Compare Instant objects by calling the isBefore or isAfter methods.
Boolean cancelledEarlyEnough = cancellation.isBefore ( twentyFourHoursEarlier );
A Duration represents a span of time as a total number of seconds plus a fraction of a second in nanoseconds. We use this here to help with the mathematics, verifying we got the expected result of 23 hours. The toString method uses the standard ISO 8601 durations format of PT23H where P marks the beginning, T separates the years-months-days portion from hours-minutes-seconds portion, and H means “hours”.
Duration cancellationNotice = Duration.between ( cancellation , booking );
Dump to console.
System.out.println ( "zonedBooking: " + zonedBooking + " | booking: " + booking + " | twentyFourHoursEarlier: " + twentyFourHoursEarlier + " | cancellation: " + cancellation + " | cancelledEarlyEnough: " + cancelledEarlyEnough + " | cancellationNotice: " + cancellationNotice );
zonedBooking: 2016-02-25T16:00+01:00[Europe/Madrid] | booking: 2016-02-25T15:00:00Z | twentyFourHoursEarlier: 2016-02-24T15:00:00Z | cancellation: 2016-02-24T16:00:00Z | cancelledEarlyEnough: false | cancellationNotice: PT23H
Present to user by applying their desired/expected time zone. Specify an Instant and a ZoneId to get a ZonedDateTime.
ZoneId zoneId_Presentation = ZoneId.of( "Europe/Madrid" );
ZonedDateTime zdtBooking = ZonedDateTime.ofInstant( booking , zoneId_Presentation );
ZonedDateTime zdtCancellationGrace = ZonedDateTime.ofInstant( twentyFourHoursEarlier , zoneId_Presentation );
ZonedDateTime zdtCancellation = ZonedDateTime.ofInstant( cancellation , zoneId_Presentation );
Let java.time localize for you by specifying a short-medium-long flag and a Locale for the human language in which to (a) translate name of day/month, (b) use cultural norms for ordering of the date-time parts, choosing comma versus period, and such.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL );
formatter = formatter.withLocale( new Locale("es", "ES") );
String output = zdtBooking.format( formatter );
jueves 25 de febrero de 2016 16H00' CET
Ignore Server Time Zone
Your Question mentioned the server’s time zone. You should never depend on the server’s time zone as it is out of your control as a programmer, and it is easily changed with little thought by a sysadmin. In addition, your JVM’s current default time zone may be based on the that of the host operating system. But not necessarily. A flag on the command-line launching of the JVM may set the JVM’s default time zone. Even more dangerous: Any code on any thread of any app within the JVM can set the time zone and immediately affect your app -- during runtime!
If you do not specify a time zone, the JVM’s current default is implicitly applied. Always specify your desired/expected time zone explicitly, as seen in code above.
The above also goes for the current default Locale. Always specify the desired/expected Locale rather than depending implicitly on the JVM’s current default.
The plane is leaving at the same moment in time, no matter where in the world you are. This is also known as a timestamp. For such situations, storing a timestamp would be a proper solution. In java, current timestamp may be retrieved via System.currentTimeMillis(). This value does not depend on the time zone of your server and contains amount of millis since 1970 in UTC.
When user books the flight, you will need to convert user's selected time+timezone into the timestamp. When displaying, timestamps should be converted to user's timezone.
Validation with timestamps is a simple operation then: planeTakeOffTs - NOW > 24*60*60*1000
You may also want to use such library as joda-time (which has been included into inspired Java v8 java.time) to handle the dates and time.
Basil Bourque, to answer your last comment, I did the test below.
As you can see, setting the timezone has effect to LocalDateTime and fortunately.
Where you right is this is not the right solution and should be used if we do not have another solution.
public static void main(String[] args) {
Instant instant = Instant.now();
LocalDateTime local = LocalDateTime.now();
ZonedDateTime zone = ZonedDateTime.now();
System.out.println("====== WITHOUT 'UTC' TIME ZONE ======");
System.out.println("instant : " + instant );
System.out.println("local : " + local);
System.out.println("zone : " + zone);
System.out.println("instant converted : " + instant.atZone(ZoneId.of("Europe/Paris")).toLocalDateTime());
System.out.println("====================================");
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Instant instant2 = Instant.now();
LocalDateTime local2 = LocalDateTime.now();
ZonedDateTime zone2 = ZonedDateTime.now();
System.out.println("====== WITH 'UTC' TIME ZONE ======");
System.out.println("instant2 : " + instant2 );
System.out.println("local2 : " + local2);
System.out.println("zone2 : " + zone2);
System.out.println("instant2 converted : " + instant2.atZone(ZoneId.of("Europe/Paris")).toLocalDateTime());
System.out.println("==================================");
}
And the output :
====== WITHOUT 'UTC' TIME ZONE ======
instant : 2019-02-14T17:14:15.598Z
local : 2019-02-14T18:14:15.682
zone : 2019-02-14T18:14:15.692+01:00[Europe/Paris]
instant converted : 2019-02-14T18:14:15.598
====================================
====== WITH 'UTC' TIME ZONE ======
instant2 : 2019-02-14T17:14:15.702Z
local2 : 2019-02-14T17:14:15.702
zone2 : 2019-02-14T17:14:15.702Z[UTC]
instant2 converted : 2019-02-14T18:14:15.702
==================================
Note that as many developers use Hibernate, it provides this property hibernate.jdbc.time_zone which helps a lot when dealing whith date. Setting this property to UTC has effect to LocalDateTime and ZonedDateTime.
In my application, it saves a preference which is an integer that is the number of days since the epoch. (not relevant but it is used to create backups every x days)
Given this value, how can I reliably create an instance of joda DateTime?
I'm tempted to convert it to milliseconds by doing the multiplication value * 24 * 60 * 60 * 1000 but this will be wrong due to astronomy / solar time?
Multiplying number of days into the number of milliseconds might be more readable if you use a library function. I highly recommend using Joda. :)
You have a number of days since epoch (GMT), and you want a DateTime (date + time + timezone). At a bare minimum, before you get further, you'll need to specify how you want to treat the time and timezone calculation.
The simplest way (which might not be what you intend) would be to create an instant in the local timezone representing the beginning of epoch, and then use plusDays to add the right number of days:
// in class - note that this will cache the current default timezone
private static final DateTime EPOCH_START_INSTANT = new DateTime(0);
// West of Greenwich, this will actually represent the "day" before.
// Day 0 will be Dec 31, 1969, local time.
DateTime localTime = EPOCH_START_INSTANT.plusDays(yourDayCount);
For the purpose of creating a backup every X days, you might instead want a LocalDate initialized at epoch (January 1, 1970), plus the number of days you want. That could then be changed to a specified local time relatively easily.
// in class
private static final EPOCH_LOCALDATE = new LocalDate(1970, 1, 1);
private static final THREE_AM = new LocalTime(3, 0);
LocalDate localDate = EPOCH_LOCALDATE.plusDays(yourDayCount);
// Midnight (or closest valid time thereto) in the default time zone
DateTime startOfDay = localDate.toDateTimeAtStartOfDay();
// 3 AM in the default time zone
DateTime threeAM = localDate.toDateTime(THREE_AM);
The answer by Jeff Bowman is correct.
I'll show the same idea in the java.time framework, intended to succeed Joda-Time.
java.time
Java 8 and later has the new java.time framework built-in. These new classes supplant the old java.util.Date/.Calendar classes. They are inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project.
I am assuming your count-of-day-from-epoch is in UTC. So we can use the Instant class, basically a count of nanoseconds from the first moment of 1970 in UTC.
long myCountOfDays = 16_721L;
Instant instant = Instant.EPOCH.plus ( myCountOfDays , ChronoUnit.DAYS );
Let's adjust into a time zone. Choosing Montreal arbitrarily. Use a proper time zone name, never the 3-4 letter codes like "EST" or "IST".
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
Dump to console.
System.out.println ( "myCountOfDays: " + myCountOfDays + " from epoch: " + Instant.EPOCH + " in UTC is: " + instant + " and in Montréal is: " + zdt + "." );
When run.
myCountOfDays: 16721 from epoch: 1970-01-01T00:00:00Z in UTC is: 2015-10-13T00:00:00Z and in Montréal is: 2015-10-12T20:00-04:00[America/Montreal].
According to the FAQ:
Joda-Time does not support leap seconds. Leap seconds can be supported by writing a new, specialized chronology, or by making a few enhancements to the existing ZonedChronology class. In either case, future versions of Joda-Time will not enable leap seconds by default. Most applications have no need for it, and it might have additional performance costs.
That suggests to me that you need not worry about that aspect.
But rather than doing the math, I would use DateTime#plusDays or MutableDateTime#addDays instead, using The Epoch as your starting point.
I assume, though, that your "days since The Epoch" is allowing for leap days (and that you're using the Gregorian chronology so JodaTime is, too).
I am trying to calculate the duration between two instances of LocalDateTime. The special thing here is that each instance of LocalDateTime could be from ANYWHERE in the world:
LocalDateTime start could be from Nevada and LocalDateTime end could be from Tokyo. Each "time" associated with the LocalDateTime is, obviously enough, local to that location.
So if I said...
LocalDateTime start = LocalDateTime.parse("2015-07-14T10:00:00"); and said that start represented Chicago, that would mean 10:00 AM in Chicago time.
Then I could say...
LocalDateTime end = LocalDateTime.parse("2015-07-14T03:00:00"); and end represents Moscow, so it is 3:00AM in Moscow time.
Can I create a robust enough solution that will allow start and end to represent any cities in the world and still correctly calculate the duration between the two?
"LocalDateTime" Does Not Mean A Particular Locality
I think you misunderstand the purpose of LocalDateTime. The "local" means any locality, not a specific locality. As in "Christmas starts at midnight on December 25, 2015" where we mean any locality’s midnight. Christmas starts in Paris several hours earlier than Montréal, for example.
If you know the date-time is meant to represent a date-time in Nevada, the use a Joda-Time DateTime assigned the proper time zone name of America/Boise. In the new java.time package (Tutorial) built into Java 8 and later, use a ZonedDateTime object with assigned time zone.
Similarly, if you know the date-time is local to Tokyo, do not use LocalDateTime. Use a Joda-Time DateTime with an assigned time zone of Asia/Tokyo.
Elapsed
Elapsed time between a pair of LocalDateTime instances makes no sense. For example, the times may be 14:00 and 18:00 on the same date, but that does not mean four hours difference. If you really meant 14:00 in Paris and 18:00 in Chicago, that would be several hours difference, not two.
I am not discussing calculating elapsed time as that has been handled many many times on StackOverflow. I'm trying to clarify some concepts here. Then you can move on to the existing Questions & Answers for calculating elapsed time.
Databases Store UTC
Generally in SQL databases you should be using the data type TIMESTAMP WITH TIME ZONE (a.k.a. TIMESTAMPZ with a Z for "zulu"). This misnomer actually means "with respect for time zone". Incoming data with an offset from UTC or other time zone information is adjusted to UTC. The data's offset or time zone is not preserved.
The SQL data type TIMESTAMP WITHOUT TIME ZONE (a.k.a. TIMESTAMP) means the same as a LocalDateTime in Java: no time zone at all. Not tied to the timeline. Any offset or time zone information with input data is ignored, no adjustment made.
Postgres doc may help explain.
Stick With UTC
When retrieving such a value from the database, the UTC value may be adjusted to a particular time zone by your admin tool (such as pgAdmin in Postgres) or your database driver or by your app.
In your app it is generally best to keep your date-time values in UTC as much as possible. Do nearly all of your storage, business logic, and data exchange in UTC. Only adjust to a particular time zone when expected by the user.
To Convert A LocalDateTime To A Time Zone
If you do have a LocalDateTime object, and you want to assign it a time zone, here is some example code. We also adjust to get the very same moment as seen in Montréal and in UTC. First the example is shown in Joda-Time, then in java.time.
Joda-Time
Example in Joda-Time 2.8.
LocalDateTime ldt = new LocalDateTime( "2015-07-14T10:00:00" ); // Nowhere in particular.
DateTimeZone zoneChicago = DateTimeZone.forID( "America/Chicago" );
DateTime dateTimeChicago = ldt.toDateTime( zoneChicago );
DateTime dateTimeMontreal = dateTimeChicago.withZone( DateTimeZone.forID( "America/Montreal" ) );
DateTime dateTimeUtc = dateTimeChicago.withZone( DateTimeZone.UTC );
Dump to console.
System.out.println( "LocalDateTime (nowhere): " + ldt );
System.out.println( "Chicago: " + dateTimeChicago );
System.out.println( "Montréal: " + dateTimeMontreal );
System.out.println( "UTC: " + dateTimeUtc);
When run.
LocalDateTime (nowhere): 2015-07-14T10:00:00.000
Chicago: 2015-07-14T10:00:00.000-05:00
Montréal: 2015-07-14T11:00:00.000-04:00
UTC: 2015-07-14T15:00:00.000Z
java.time
Example in java.time of Java 8 Update 51.
LocalDateTime ldt = LocalDateTime.parse( "2015-07-14T10:00:00" ); // Nowhere in particular.
ZoneId zoneChicago = ZoneId.of( "America/Chicago" );
ZonedDateTime zdtChicago = ZonedDateTime.of( ldt, zoneChicago );
ZonedDateTime zdtMontreal = zdtChicago.withZoneSameInstant( ZoneId.of( "America/Montreal" ) );
ZonedDateTime zdtUtc = zdtChicago.withZoneSameInstant( ZoneOffset.UTC ); // ZoneOffset is a subclass of ZoneId.
Dump to console.
System.out.println( "LocalDateTime (nowhere): " + ldt );
System.out.println( "Chicago: " + zdtChicago );
System.out.println( "Montréal: " + zdtMontreal );
System.out.println( "UTC: " + zdtUtc);
When run.
LocalDateTime (nowhere): 2015-07-14T10:00
Chicago: 2015-07-14T10:00-05:00[America/Chicago]
Montréal: 2015-07-14T11:00-04:00[America/Montreal]
UTC: 2015-07-14T15:00Z
I am trying to convert GMT+2 time to GMT-4 time.But i am getting unexpected results.Help me on how to achieve that conversion of one time zone time to other time zone time.
originTime = "2015-08-15T10:25:00";
SimpleDateFormat converter = new SimpleDateFormat("yyyy-MM-dd hh:mm");
converter.setTimeZone(TimeZone.getTimeZone("GMT-4"));
GregorianCalendar oc = originTime.toGregorianCalendar();
String OriginStart=converter.format(oc.getTime());
The above code has to give the originStart time lesser than the given time If it is GMT-4.
But Im getting OriginStart time greater than the given time.
Assuming the timzone strings are valid (as i haven't tried it) try something like
String originTime = "2015-08-15 10:25";
SimpleDateFormat converter = new SimpleDateFormat("yyyy-MM-dd hh:mm");
converter.setTimeZone(TimeZone.getTimeZone("GMT+10"));
Date date = converter.parse (originTime);
converter.setTimeZone(TimeZone.getTimeZone("GMT-4"));
String OriginStart=converter.format(date);
Padding Zero
Generally, use a padding zero for offset hours. But this is not a problem in your specific code. At least not according to the doc for TimeZone class which explicitly accepts single digit.
The ISO 8601 standard requires offset hours to have a padding zero. So use -04 rather than -4.
By the way, the original release of java.time had a bug where it failed to parse offsets values of just hour without menu. So in that case, use -04:00 rather than -04.
Named Time Zone
A time zone is more that just an offset from UTC (GMT). A time zone includes rules about Daylight Savings Time (DST) and other anomalies, past, present, and future. So use a specific time zone name if you have one in mind.
An example of a +02:00 time zone name would be Africa/Bujumbura. An example of -04:00, America/Martinique.
Avoid java.util.Date
The java.util.Date/.Calendar and SimpleDateFormat classes are notoriously troublesome and confusing. Perhaps the worst of the bundled Java libraries. Avoid them.
Instead use either Joda-Time or the new java.time package built into Java 8 (inspired by Joda-Time).
ISO 8601
The ISO 8601 standard defines sensible unambiguous string formats for date-time values. Your input string format complies with this wise standard.
Both Joda-Time and java.time parse and generate strings in ISO 8601 format by default. So no need to specify a formatter.
Example
Example code written in Joda-Time 2.7.
Define the input, formatted in ISO 8601 without any offset from UTC.
String input = "2015-08-15T10:25:00";
Specify time zones if input and output.
DateTimeZone zoneInput = DateTimeZone.forOffsetHours( 2 );
// DateTimeZone zoneInput = DateTimeZone.forID( "Africa/Bujumbura" ); // Preferably the specific time zone name.
DateTimeZone zoneTarget = DateTimeZone.forOffsetHours( -4 );
// DateTimeZone zoneTarget = DateTimeZone.forID( "America/Martinique" ); // Preferably the specific time zone name.
Parse the string, while assigning a time zone. Then adjust the time zone.
DateTime dateTimeOriginal = new DateTime( input , zoneInput );
DateTime dateTimeTarget = dateTimeOriginal.withZone( zoneTarget );
Dump to console.
System.out.println( "zoneInput / zoneTarget : " + zoneInput + " / " + zoneTarget );
System.out.println( "dateTimeOriginal : " + dateTimeOriginal );
System.out.println( "dateTimeTarget : " + dateTimeTarget );
When run.
zoneInput / zoneTarget : +02:00 / -04:00
dateTimeOriginal : 2015-08-15T10:25:00.000+02:00
dateTimeTarget : 2015-08-15T04:25:00.000-04:00
I tried to use SimpleDateFormat to do the work,
but I don't know how to handle the T in the string "2008-08-01T15:47:00.557", can anyone help me with this?
You need to use the format "yyyy-MM-dd'T'hh:mm:ss.SSS".
In an additional note, if you are trying to handle xml dates check out this question: Convert Java Date into XML Date Format (and vice versa)
I'm not very very sure. But if I remember good, you have to surround the T by single quotes in your format.
String yourFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS";
since your example was with 24H format and not AM/PM one
you should use HH (capital) instead of hh
like this
String EXT_JS_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
Almost this exact example is given in the API, check it out :-)
http://download.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
ISO 8601
Your string’s format happens to comply with the ISO 8601 standard.
java.time
Java 8 and later includes the java.time framework to supplant the old date-time classes used in the Question and in other Answers.
The new classes use the ISO 8601 standard by default when parsing/generating strings. So no need to specify a coded format pattern.
Time Zone
Your input string lacks any time zone or offset-from-UTC. So you must specify the time zone for which this string has meaning. If you do not specify, the parsing automatically applies your JVM’s current default time zone. Not good as that default may not be the zone intended for your string. Also, the JVM’s default can change at any moment, even during runtime.
If UTC
If your string was meant for UTC as the time zone, simply append a Z (short for “Zulu” which means UTC). Then parse as an Instant, a moment on the timeline in UTC.
String input = "2008-08-01T15:47:00.557";
Instant instant = Instant.parse ( input + "Z" );
Dump to console.
System.out.println ( "instant: " + instant );
instant: 2008-08-01T15:47:00.557Z
If Time Zone
If your string was intended for some other time zone, we need to specify. Use a proper time zone name (never the 3-4 letter codes seen in the press). Here we arbitrarily choose the Montréal time zone.
For the formatting pattern, we use one of the predefined formats for ISO 8601: DateTimeFormatter.ISO_LOCAL_DATE_TIME (the 'LOCAL' means no time zone or offset embedded within the input string).
String input = "2008-08-01T15:47:00.557";
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
formatter = formatter.withZone ( zoneId );
ZonedDateTime zdt = ZonedDateTime.parse ( input , formatter );
Dump to console. We also extract an Instant from the ZonedDateTime so you can see the same moment in UTC. Usually best to work in UTC in your business logic; only apply a time zone for output to the user.
System.out.println ( "input: " + input + " | zdt: " + zdt + " | instant of zdt: " + zdt.toInstant () );
input: 2008-08-01T15:47:00.557 | zdt: 2008-08-01T15:47:00.557-04:00[America/Montreal] | instant of zdt: 2008-08-01T19:47:00.557Z