Date time conversion in Java8 - java

I tried searching across the web, but unable to find a suitable answer and hence posting here.
I am calling another API which gives me the date-time like
"2022-02-05T17:13:20-06:00[America/Chicago]"
I would like to convert this to a format like
"2022-02-05T17:13:20.000Z" (I am unsure what the milli-second will turn out as)
Could someone help me achieve this?
I am unable to get any example for this specific conversion scenario!!!
Regards,
Sriram

For the sample values given getting to a UTC timestamp should be something like
ZonedDateTime.parse("2022-02-05T17:13:20-06:00[America/Chicago]").toInstant().toString()
The datetime value including the timezone is the canonical representation of a ZonedDateTime and therefore can be parsed as such.
Instant is a UTC timestamp that prints in the form of 2022-02-05T23:13:20Z
You could take more influence on the behavior using a DateTimeFormatter - but since both input and output seem to be standard formats it does not seem necessary.

Here below is a code snippet that I was able to generate....
But, I am unsure of that is correct. Please let me know if you feel anything is incorrect.
String requestTime = "2022-02-05T17:13:20-06:00[America/Chicago]";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX'['VV']'");
ZonedDateTime zonedDateTime = ZonedDateTime.parse(requestTime, formatter);
zonedDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"));
System.out.println(zonedDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")));

Related

Parsing PDF date using Java DateTimeFormatter

I'm trying to parse the date format used in PDFs. According to this page, the format looks as follows:
D:YYYYMMDDHHmmSSOHH'mm'
Where all components except the year are optional. I assume this means the string can be cut off at any point as i.e. specifying a year and an hour without specifying a month and a day seems kind of pointless to me. Also, it would make parsing pretty much impossible.
As far as I can tell, Java does not support zone offsets containing single quotes. Therefore, the first step would be to get rid of those:
D:YYYYMMDDHHmmSSOHHmm
The resulting Java date pattern should then look like this:
['D:']uuuu[MM[dd[HH[mm[ss[X]]]]]]
And my overall code looks like this:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("['D:']uuuu[MM[dd[HH[mm[ss[X]]]]]]");
TemporalAccessor temporalAccessor = formatter.parseBest("D:20020101",
ZonedDateTime::from,
LocalDateTime::from,
LocalDate::from,
Month::from,
Year::from
);
I would expect that to result in a LocalDate object but what I get is java.time.format.DateTimeParseException: Text 'D:20020101' could not be parsed at index 2.
I've played around a bit with that and found out that everything works fine with the optional literal at the beginning but as soon as I add optional date components, I get an exception.
Can anybody tell me what I'm doing wrong?
Thanks in advance!
I've found a solution:
String dateString = "D:20020101120000+01'00'";
String normalized = dateString.replace("'", "");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("['D:']ppppy[ppM[ppd[ppH[ppm[pps[X]]]]]]");
TemporalAccessor temporalAccessor = formatter.parseBest(normalized,
OffsetDateTime::from,
LocalDateTime::from,
LocalDate::from,
YearMonth::from,
Year::from
);
As it seems, the length of the components is ambiguous and parsing of the date without any separators thus failed.
When specifying a padding, the length of each component is clearly stated and the date can therefore be parsed.
At least that's my theory.

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

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?

DateFormat with Milliseconds in standard Java Library?

I'm wondering if there is a static String or DateFormat anywhere in the standard Java library for formatting dates 'completely'. By completely, I mean the date and time including milliseconds and timezone, something along the lines of "dd MMM yyyy HH:mm:ss.SSS zzz". It's easy to just declare the string myself, but it would be nice if I didn't have to do that for every project I use that needs millisecond-precision date parsing. I have been unable to find one so far.
As an aside, I think it's a little silly that java.util.Date#toString() doesn't account for milliseconds when the class it represents does.
Edit - Unfortunately, it is not as simple as beginning the conversion over to DateTime usage, as that is not something that is in my control. I am the 2nd most junior developer on the project. I would love to use DateTime going forward, but without the support of my supervisor, I cannot.
Also for Java 8 Date Time Api you can use
LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME);
for results like that
2017-03-27T20:46:03.852

Java time instant formatting discrepancies

The way Java time handles simple things like timestamps leaves me a little taken aback. Maybe I'm doing it wrong.
I want to generate an ISO 8601 timestamp string. The obvious way would be to create an Instance.now() and format it use DateTimeFormatter.ISO_INSTANT to format it. Except that Instance has no format() method, so I can't format it with the "instance" formatter. Imagine that.
So I have to create a ZonedDateTime from the instance. It shouldn't matter which zone I choose, so I choose UTC because that's what DateTimeFormatter.ISO_INSTANT is going to put it in anyway:
Instant.now().atZone(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)
Now I get back a string, and obviously I want to get it back to a ZonedDateTime instance, because that's what I used to format it with! So I try:
ZonedDateTime.parse(timestamp, DateTimeFormatter.ISO_INSTANT)
It complains at me that there is no time zone information. But I used a ZonedDateTime to generate it --- it's not my fault that it wouldn't let me use an Instance to format it.
Oddly Instance doesn't have a format() method, but it does have a parse() method, which, again oddly, is parsed using DateTimeFormatter.ISO_INSTANT (even though I can't format an Instance using that formatter).
As pointed out in the comments, I can use DateTimeFormatter.ISO_INSTANT.format(Instance.now()) to format an instance directly, so why isn't there an Instance.format(…)?
So just generating and parsing a timestamp seems convoluted and inconsistent. Or am I doing it wrong?
First, you can just DateTimeFormatter.ISO_INSTANT.format(Instant.now()).
Next, I don't see why you expect to parse back what you've formatted. Formatting is not guaranteed to be a lossless operation. If you format a LocalDateTime with just the year, you wouldn't expect to parse it back to LocalDateTime, would you?
And of course you can parse Instant using DateTimeFormatter.ISO_INSTANT. DateTimeFormatter.ISO_INSTANT.parse(text, Instant::from) - this is what Instant.parse(...) does.
There is no need for a format(DateTimeFormatter) method in Instant, because toString() does the job. The toString() method of Instant is implemented as:
return DateTimeFormatter.ISO_INSTANT.format(this);
Thus, all you need to do is call instant.toString().
To round-trip parse this back in, simply use parse():
Instant instant = Instant.parse(text);
Why do you need to respecify the formatter when parsing back the string?
Can't you just do ZonedDateTime.parse(timestamp);?

Datetime Parsing - Unable to get back original value

DateTimeFormatter DATEFORMAT = ISODateTimeFormat.dateTimeNoMillis();
String testDate = "2013-10-26T04:23:14-08:00";
System.out.println(testDate);
System.out.println(DATEFORMAT.parseDateTime(testDate).toString(DATEFORMAT));
Output:
2013-10-26T04:23:14-08:00
2013-10-26T05:23:14-07:00
Why are outputs off by around an hour ? Is there any other parameter I need to specify for converting DateTime back to string ?
Any help is much appreciated.
I'm assuming this is using the joda-time library. As the comments above suggest, it's a TZ issue. You can easily convert any of the times into the TZ of your choice or UTC through a method call on the DateTime object. Something along the lines of:
dt.withZone(DateTimeZone.UTC);
You're getting different results since the default behavior is to print the DateTime in the system's current timezone.

Categories