java.time.format.DateTimeParseException: could not be parsed at index 0 - java

I am trying to convert a String to timestamp.
my string contains time and time zone ('05:03:05.875+02:00') but I get the following error:
error
java.time.format.DateTimeParseException: Text '05:03:05.875+02:00'
could not be parsed at index 0
Code
String timewithZone= "05:03:05.875+02:00";
DateTimeFormatter formatter=DateTimeFormatter.ISO_OFFSET_DATE_TIME;
final ZonedDateTime a2=ZonedDateTime.parse(timewithZone,formatter);

String timewithZone = "05:03:05.875+02:00";
OffsetTime time = OffsetTime.parse(timewithZone);
System.out.println("Parsed into " + time);
This outputs
Parsed into 05:03:05.875+02:00
Your string contains a time and an offset, but no date. This conforms nicely, neither with an ISO_OFFSET_DATE_TIME nor a ZonedDateTime, but with an OffsetTime, a seldom used class that I think is there exactly because such a thing sometimes occurs in XML.
There is also an ISO_OFFSET_TIME formatter built in, but since this is the default format for OffsetTime we do not need to specify it.

It is failing because your string does not have the date related tokens. Check the example in the official documentation. In order to make it work you will need to add year/month/day data:
String timewithZone= "2018-07-3T05:03:05.875+02:00";

You cannot use the DateTimeFormatter.ISO_OFFSET_DATE_TIME because your date format does not adhere to that.
In fact, you don't even have a real date because there is no date component, only a time component.
You could define your own SimpleDateFormat instance with the format you're receiving, but you'll have to handle the fact that this data isn't really all that useful without date information. For example, that offset doesn't really tell us that much, because it might be in some region's Daylight Savings Time (DST) or not. And this heavily depends on on what actual DATE it is, not just what time.
You'll have to find out what the provider of this data even means with this, because right now you simply don't have enough information to really parse this into a proper date.
If this data just means a simple time stamp, used for for example saying "our worldwide office hours lunch time is at 12:30" then you could us the LocalTime class. That would be one of the few cases where a time string like this without a date is really useful. I have a sneaking suspicion this is not your scenario though.

A workaround may be
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSSz");
String str = "05:03:05.875+02:00";
LocalTime time = LocalTime.parse(str, formatter);
System.out.println(time);
I tried the code in the format what you are getting,
Output :
05:03:05.875
Is this the one you are looking for?

Related

what is the actual return type for LocalDate.now().toString()

I am trying to save LocalDateTime to DB. So my scenario is I have consumer and producer. Producer generated some code and gives it to consumer, and consumer saves the entries to database.
Code on Producer Side
LocalDate.now().toString() // returns 2021-07-13T12:25:38.841775700 sometimes it returns 2021-07-13T12:25:38.841 so basically after the last decimal point the precision can be anything.
Code on Consumer side
On the consumer side i want to save entries from received from producer into the db for that i need to convert the str to LocalDateDime.
private static DateTimeFormatter timeFormatterInMs= DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
public static LocalDateTime unmarshalDateTime(final String dateTimeStr) {
return dateTimeStr == null ? null : LocalDateTime.parse(str, timeFormatterInMs);
}
Here the problem is what is the format for return type of LocalDateTime
i know it return data in the format yyyy-MM-dd'T'HH:mm:ss.SSS by in our case ms have sometimes 9, sometimes 6 decimal places? if i will give this string to the function unmarshalDateTime(..) the function will break and it wont work properly. because it expects the ms part to be 3 decimal places. what to do about it
The direct answer to your question is in the documentation of LocalDateTime.toString() (link at the bottom):
Outputs this date-time as a String, such as 2007-12-03T10:15:30.
The output will be one of the following ISO-8601 formats:
uuuu-MM-dd'T'HH:mm
uuuu-MM-dd'T'HH:mm:ss
uuuu-MM-dd'T'HH:mm:ss.SSS
uuuu-MM-dd'T'HH:mm:ss.SSSSSS
uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS
The format used will be the shortest that outputs the full value of
the time where the omitted parts are implied to be zero.
To parse such a string back into a LocalDateTime don’t use any formatter at all. The one-arg LocalDateTime.parse(CharSequence) parses every one of those formats.
Let me show you:
System.out.println(LocalDateTime.parse("2021-07-13T12:25:38.841775700"));
System.out.println(LocalDateTime.parse("2021-07-13T12:25:38.841"));
System.out.println(LocalDateTime.parse("2021-07-13T12:26"));
Output:
2021-07-13T12:25:38.841775700
2021-07-13T12:25:38.841
2021-07-13T12:26
This said Ali Behzadian Nejad is correct in his answer: assuming that those values are supposed to define points in time, LocalDateTime is the wrong type for them. Use Instant. If you can, use timestamp with time zone on the SQL side. Depending on your JDBC driver you may or may not need to convert via OffsetDateTime. If you need to store strings, Instant.toString() too can produce different formats and can parse each and every one of them back through the one-arg Instant.parse().
Documentation links
LocalDateTime.toString()
LocalDateTime.parse(CharSequence)
Storing local dates in database is not a good idea because they are not instants of time, they are just localized presentation of time.
Create an Instant object from LocalTime and its timezone and save that time Instant in database column with Timestamp type:
LocalDateTime localDateTime = ...
Instant instant = localDateTime.atZone(ZoneId.of("Europe/Paris")).toInstant();
From Java documentation:
This class [LocalDateTime] does not store or represent a time-zone.
Instead, it is a description of the date, as used for birthdays,
combined with the local time as seen on a wall clock. It cannot
represent an instant on the time-line without additional information
such as an offset or time-zone.
With jdk11: The format used will be the shortest that outputs the full value of the time where the omitted parts are implied to be zero.
Also there have LocalDate.format to generate a time string by format.
BTW, if you want save time to database I suggest use long or Timestamp instead of String
You can use a DateTimeFormatter that considers different patterns in order to parse Strings with different amounts of fractions-of-second (here: 6 or 9):
public static void main(String[] args) throws Exception {
String datetime = "2021-07-13T12:25:38.841775700";
String datetimeShort = "2021-07-13T12:25:38.841775";
// provide a formatter that "knows" two different patterns
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
"[uuuu-MM-dd'T'HH:mm:ss.nnnnnnnnn][uuuu-MM-dd'T'HH:mm:ss.SSSSSS]");
// parse the one with 9 fractions-of-second
LocalDateTime ldt = LocalDateTime.parse(datetime, dtf);
// and the one with 6 using the same formatter
LocalDateTime ldtShort = LocalDateTime.parse(datetimeShort, dtf);
// output the parsed LocalDateTimes
System.out.println(ldt + " and " + ldtShort + " are successfully parsed");
}
This outputs
2021-07-13T12:25:38.841775700 and 2021-07-13T12:25:38.841775 are successfully parsed

How to get OffsetDateTime->LocalDateTime and save this as UTC?

I didn't find a suitable answer for my problem even after a lot of searching.
It's a DateConvertUtil class in a Java API.
This is kind of a refactoring/feature task.
I have a Method, which parses a given date String, formats it with the help of another Method and returns a LocalDateTime(this kinda has to be - too much dependencies).
I want to get the Timezone of the User, convert(or maybe don't) to LocalDateTime BUT don't want to save the LocalDateTime but the UTC one everytime.
My Problem now is how to approach this.
I don't seem to get the Offset.
The parser was working before, but only for LocaldateTime, the formatter works too.
So far I have
public static LocalDateTime parseIso8601(String date) {
if (date == null || date.isEmpty() || date.trim().equalsIgnoreCase("") || date.length() < 10) throw new
IllegalArgumentException("Date cannot by empty or smaller than 10 characters for parsing! Minimum date " +
"is yyyy-MM-dd");
LocalDateTime localDateTime;
OffsetDateTime offsetDateTime = OffsetDateTime.now();
offsetDateTime.toInstant().atZone(ZoneOffset.UTC);
localDateTime = offsetDateTime.toLocalDateTime();
return localDateTime.parse(date, buildIso8601Formatter());
So I have read some about ZonedDateTime and Timestamps, but maybe I just can't think straight.
I appreciate any help.
It’s not very clear. You may be after something like the following:
ZoneId userTimeZone = ZoneId.systemDefault();
String date = "2019-12-25";
LocalDateTime localDateTime = LocalDate.parse(date).atStartOfDay();
System.out.println("localDateTime: " + localDateTime);
OffsetDateTime utcDateTime = localDateTime.atZone(userTimeZone)
.toOffsetDateTime()
.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println("utcDateTime: " + utcDateTime);
When I run this snippet in my time zone (Europe/Copenhagen), the output is:
localDateTime: 2019-12-25T00:00
utcDateTime: 2019-12-24T23:00Z
You said:
I want to get the Timezone of the User, …
The way to do this differs. In a standalone application you may try ZonedId.systemDefault() as in the above code. It gives you the default time zone of the JVM, which may or may not agree with what the user intends. And the setting can be changed at any time from another part of your program or another program running in the same JVM, so is fragile. On a server that has users in different time zones ZoneId.systemDefault() won’t work at all. You need to have the time zone passed from some client/browser. There are ways, and you may search for the way to do it in your setup.
… BUT don't want to save the LocalDateTime but the UTC one everytime.
That’s good, using UTC is recommended. Again the way to do this depends on your setup. If saving into an SQL database you can save either an OffsetDateTime or an Instant (provided that you’re using a JDBC 4.2 compliant driver, which is highly likely) so the above code may suffice. If you need to store the date and time as a string, use Instant.toString() for producing a string in ISO 8601 format. I recommend against using a LocalDateTime for you date and time in UTC since it doesn’t “know” itself that it is in UTC, which makes the risk of an error too great. Other examples:
Instant utcInstant = localDateTime.atZone(userTimeZone).toInstant();
System.out.println("utcInstant: " + utcInstant);
String utcDateTimeString = utcDateTime.toString();
System.out.println("utcDateTimeString: " + utcDateTimeString);
utcInstant: 2019-12-24T23:00:00Z
utcDateTimeString: 2019-12-24T23:00Z
The name utcInstantis really either redundant or nonsense since an Instant on one hand is independent of time zones, on the other hand always prints in UTC. I couldn’t readily think of a better name, sorry. Anuway it is fine for storing if you can in your setup.

DateTime Manipulation in C# vs Java

I'm new to Java. I have a time I am getting from a web-page, this is in the "hh:mm" format (not 24 hour). This comes to me as a string. I then want to combine this string with todays date in order to make a Java Date I can use.
In C#:
string s = "5:45 PM";
DateTime d;
DateTime.TryParse(s, out d);
in Java I have attempted:
String s = "5:45 PM";
Date d = new Date(); // Which instantiates with the current date/time.
String[] arr = s.split(" ");
boolean isPm = arr[1].compareToIgnoreCase("PM") == 0;
arr = arr[0].split(":");
int hours = Integer.parseInt(arr[0]);
d.setHours(isPm ? hours + 12 : hours);
d.setMinutes(Integer.parseInt(arr[1]));
d.setSeconds(0);
Is there a better way to achieve what I want?
Is there a better way to achieve what I want?
Absolutely - in both .NET and in Java, in fact. In .NET I'd (in a biased way) recommend using Noda Time so you can represent just a time of day as a LocalTime, parsing precisely the pattern you expect.
In Java 8 you can do the same thing with java.time.LocalTime:
import java.time.*;
import java.time.format.*;
public class Test {
public static void main(String[] args) {
String text = "5:45 PM";
DateTimeFormatter format = DateTimeFormatter.ofPattern("h:mm a");
LocalTime time = LocalTime.parse(text, format);
System.out.println(time);
}
}
Once you've parsed the text you've got into an appropriate type, you can combine it with other types. For example, to get a ZonedDateTime in the system time zone, using today's date and the specified time of day, you might use:
ZonedDateTime zoned = ZonedDateTime.now().with(time);
That uses the system time zone and clock by default, making it hard to test - I'd recommend passing in a Clock for testability.
(The same sort of thing is available in Noda Time, but slightly differently. Let me know if you need details.)
I would strongly recommend against using java.util.Date, which just represents an instant in time and has an awful API.
The key points here are:
Parse the text with a well-specified format
Parse the text into a type that represents the information it conveys: a time of day
Combine that value with another value which should also be carefully specified (in terms of clock and time zone)
All of these will lead to clear, reliable, testable code. (And the existing .NET code doesn't meet any of those bullet points, IMO.)
To parse the time, you can do as explained in #Jon Skeet's answer:
String input = "5:45 PM";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("h:mm a", Locale.ENGLISH);
LocalTime time = LocalTime.parse(input, parser);
Note that I also used a java.util.Locale because if you don't specify it, it'll use the system's default locale - and some locales can use different symbols for AM/PM field. Using an explicit locale avoids this corner-case (and the default locale can also be changed, even at runtime, so it's better to use an explicit one).
To combine with the today's date, you'll need a java.time.LocalDate (to get the date) and combine with the LocalTime, to get a LocalDateTime:
// combine with today's date
LocalDateTime combined = LocalDate.now().atTime(time);
Then you can format the LocalDateTime using another formatter:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
System.out.println(combined.format(fmt));
The output is:
16/08/2017 17:45
If you want to convert the LocalDateTime to a java.util.Date, you must take care of some details.
A java.util.Date represents the number of milliseconds since 1970-01-01T00:00Z (aka Unix Epoch). It's an instant (a specific point in time). Check this article for more info.
So, the same Date object can represent different dates or times, depending on where you are: think that, right now, at this moment, everybody in the world are in the same instant (the same number of milliseconds since 1970-01-01T00:00Z), but the local date and time is different in each part of the world.
A LocalDateTime represents this concept of "local": it's a date (day, month and year) and a time (hour, minute, second and nanosecond), but without any relation to a specific timezone.
The same LocalDateTime object can represent different instants in time in different timezones. So, to convert it to a Date, you must define in what timezone you want it.
One option is to use the system's default timezone:
// convert to system's default timezone
ZonedDateTime atDefaultTimezone = combined.atZone(ZoneId.systemDefault());
// convert to java.util.Date
Date date = Date.from(atDefaultTimezone.toInstant());
But the default can vary from system/environment, and can also be changed, even at runtime. To not depend on that and have more control over it, you can use an explicit zone:
// convert to a specific timezone
ZonedDateTime zdt = combined.atZone(ZoneId.of("Europe/London"));
// convert to java.util.Date
Date date = Date.from(zdt.toInstant());
Note that I used Europe/London. The API uses IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin).
Avoid using the 3-letter abbreviations (like CST or PST) because they are ambiguous and not standard.
You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().
And there's also the corner cases of Daylight Saving Time (when a LocalDateTime can exist twice or can't exist due to overlaps and gaps). In this case, Jon's solution using ZonedDateTime avoids this problem).

How to change miillisecond to Date Object in yyyy-MM-dd HH:mm:ss format [duplicate]

This question already has answers here:
Unix epoch time to Java Date object
(7 answers)
Convert timestamp in milliseconds to string formatted time in Java
(10 answers)
Closed 5 years ago.
How to change milliseconds to Date object in yyyy-MM-dd HH:mm:ss format like 2017-04-12 23:14:52?
You cannot do that. For a couple of reasons.
TL;DR: Don’t use Date, use Instant. Neither of these can have a format in them. Formatting into a string is dependent on time zone, so you need to choose a time zone.
First, I understand from the discussion that you are asking for a java.util.Date object having the format yyyy-MM-dd HH:mm:ss. A Date object does not have and cannot have a format in it. The thing you should try to understand here is the difference between data itself and presentation of data to a user. An int may hold the value 25389, but it doesn’t hold it in the format 25389 (in fact the internal representation is quite different from 25389). The same int may be presented to a user as 25389, 000025389, 25,389 or +25389, just to mention a few out of many possibilities. The formatting happens outside the int while the int stays just the same.
Similarly, a Date object holds a point in time. The same date may be formatted into for example 2017-04-12 23:14:52 or April 12, 2017 11:14:52 PM. It may even be formatted for different time zones, which would be a good idea if the system has users in different time zones. Alternatively we may show the user a calendar leaf and/or a clock showing the time. Again, formatting happens outside of the Date while the Date stays just the same.
Elaborating on the time zone issue, the same point in time represented by the same millisecond value could be formatted to 2017-04-12 17:44:52 in UTC, 2017-04-12 19:44:52 in my time zone, 2017-04-12 23:14:52 in Asia/Kolkata time zone or even 2017-04-13 05:44:52 in Pacific/Auckland time zone. Note that in the last case not even the date is the same. So there is not just one way to change your milliseconds into the format you asked for. We need to know which time zone you want it for before we can help you.
So what I believe you need is not one thing, but two
A way to store your point in time in your program.
A way to format your point in time into a string in yyyy-MM-dd HH:mm:ss format for a user in some time zone.
For storing your point in time, use either of
A long for the milliseconds value you already have
A java.time.Instant object.
Why didn’t I mention java.util.Date? Because this class is long outdated. Its design turned out to be troublesome very quickly. They tried to repair it by deprecating most of the methods and introducing java.util.Calendar, but that didn’t work very well either. Finally, drawing on the experiences from a library known as Joda-Time they introduced the java.time classes in Java 8 in 2014. That’s three years ago as of writing, and counting. So IMHO we should by now have thrown Date and friends overboard and started using the newer classes. So prefer Instant over Date.
Changing your milliseconds to an Instant is straightforward:
long milliseconds = 1492019092000L;
Instant pointInTime = Instant.ofEpochMilli(milliseconds);
For formatting your instant into a string for the user, as I said, we require a time zone. Then do
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
String formattedDateTimeString = pointInTime.atZone(ZoneId.of("Asia/Kolkata"))
.format(formatter);
So you need to fill in the desired time zone where I put ZoneId.of("Asia/Kolkata"). If you want to use the JVM’s current time zone setting, just fill in ZoneId.systemDefault(). Beware, though, that the time zone setting may be changed, even by an unrelated program running in the same JVM, so relying on this may be fragile.
The result of the above code snippet is a string like
2017-04-12 23:14:52
PS If after reading the above you really insist, here’s how to get a java.util.Date from the above:
Date myOutdatedDateInstance = Date.from(pointInTime);
(and excuse me for repeating, it still doesn’t have the desired format, that is not possible).
You can try this sample code.
public class MillDateConverter {
public static String dFormat = "yyy-MM-dd HH:mm:ss";
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dFormat);
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
long milliSec=Long.parseLong("1086073200000");
System.out.println(milliSec);
calendar.setTimeInMillis(milliSec);
System.out.println(simpleDateFormat.format(calendar.getTime()));
}
}

Human readable and parsable date format in Java

I want to save a Date object to a readable string (for example 22/10/2009 21:13:14) that is also parsable back to a Date object.
I have tried many things and the best I could find was to use DateFormater for parsing and formating but it has a setback. When you format a date you lose seconds information. I tried to find if there is an option to format it and display the seconds (even better would be to the millisecond level since that's the resolution the Date object allows you to have) but I came up short.
Any ideas?
Take a look at java.text.SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS");
Date dt = new Date();
String S = sdf.format(dt); // formats to 09/23/2009 13:53:28.238
Date dt2 = sdf.parse(S); // parses back
SimpleDateFormat can format and parse a date based on a very simple pattern system that include second and even milliseconds.
Other answers are all good.
But when doing this kind of thing please pick a format that sorts properly when coded as a string.... "yyyy/MM/dd HH:mm:ss" is fine. It always astounds me when software engineers pick a date format which doesn't sort in the obvious, convenient way.
You'll save your fellow developers a lot of pain at some distant point in the future - think of it as good karma :-)
ISO 8601
Use ISO 8601 format.
It’s flexible, it includes seconds and fraction of second if there are any, but you may also leave them out if they are 0.
It’s standard, so more and more tools format and parse it. Great for serialization for storage or data interchange.
It goes like 2009-10-22T21:13:14, I should say it’s pretty human-readable (though the T in the middle that denotes the start of the time part may feel unusual at first).
The strings sort properly, as mikera requested in another answer, as long as the years are in the four-digit range from 1000 through 9999.
The classes of java.time, the modern Java date and time API, as well as those of Joda Time parse ISO 8601 as their default, that is, without any explicit formatter, and produce the same format from their toString methods.
A modest demonstration of using java.time:
LocalDateTime dateTime = LocalDateTime.of(2009, 10, 22, 21, 13, 14);
String readableString = dateTime.toString();
System.out.println(readableString);
LocalDateTime parsedBack = LocalDateTime.parse(readableString);
System.out.println(parsedBack);
This prints two identical lines:
2009-10-22T21:13:14
2009-10-22T21:13:14
The latter System.out.println() call implicitly calls toString() once more, so this shouldn’t surprise.
A little off-topic, but I always feel the need to remind people that DateFormat and SimpleDateFormat are not thread safe! The Sun documentation clearly states this, but I keep finding code out in the wild where people stick a SimpleDateFormat in a static ...
If you want to do it a little simpler, and be spared from making your own DateFormat that most other Answers involve, you can leverage the default format in java.time.Instant:
(new Date()).toInstant.toString();

Categories