Parse ISO-8601 Datetime - java

It seems the proper form of timestamp to parse ISO-8601 in Java looks like:
"2020-02-03T23:40:17+00:00";
However mine looks like:
"2020-02-03T23:40:17+0000";
How can I parse this properly?
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class TestTime {
public static void main(String[] args) {
String ts = "2020-02-03T23:40:17+0000";
DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;
OffsetDateTime offsetDateTime = OffsetDateTime.parse(ts, timeFormatter);
long timestamp = offsetDateTime.toEpochSecond() * 1000;
}
}

You could pass a pattern to the DateTimeFormatter:
String ts = "2020-02-03T23:40:17+0000";
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZZZ");
OffsetDateTime offsetDateTime = OffsetDateTime.parse(ts, timeFormatter);
Note that the correct pattern for the offset is ZZZ instead of X or XXXX, which becomes obvious when, for example, formatting the parsed date-time back to a string:
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssX");
OffsetDateTime offsetDateTime = OffsetDateTime.parse(ts, timeFormatter);
System.out.println(offsetDateTime.format(timeFormatter));
2020-02-03T23:40:17Z
While when using ZZZ, it will format like 2020-02-03T23:40:17+0000. See the documentation for DateTimeFormatter.

Related

Trying to convert from 2023-01-11 18:27:59UTC-06:00 to 2023-01-12T00:27:59.000Z -- parsing fails

I have string date format like below
2023-01-11 18:27:59UTC-06:00
need to convert to like 2023-01-12T00:27:59.000Z (in UTC zone)
I tried the below. I am getting exception Exception in thread "main" java.time.format.DateTimeParseException: Text '2023-01-09 23:56:59UTC-05:30' could not be parsed at index 10. The exception is coming from this line:
LocalDateTime labelTime = LocalDateTime.parse(dateUTC, DateTimeFormatter.ofPattern(INPUT_FORMAT));
My short code example:
String dateUTC="2023-01-09 23:56:59UTC-05:30";
final String INPUT_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
final String OUTPUT_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";
final DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern(OUTPUT_FORMAT);
LocalDateTime labelTime = LocalDateTime.parse(dateUTC, DateTimeFormatter.ofPattern(INPUT_FORMAT));
ZoneId utcZoneId = ZoneId.of("UTC");
ZonedDateTime zdt = labelTime.atZone(utcZoneId);
System.out.println("OUT PUT Format"+dtf2.format(zdt));
Use the pattern, uuuu-MM-dd HH:mm:ss'UTC'XXX to parse the given date-time string into an OffsetDateTime and convert the result into another OffsetDateTime with ZoneOffset.UTC using OffsetDateTime#withOffsetSameInstant.
Demo:
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
class Main {
public static void main(String[] args) {
DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss'UTC'XXX", Locale.ENGLISH);
OffsetDateTime odt = OffsetDateTime.parse("2023-01-11 18:27:59UTC-06:00", parser)
.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(odt);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
String formatted = odt.format(formatter);
System.out.println(formatted);
}
}
Output:
2023-01-12T00:27:59Z
2023-01-12T00:27:59.000Z
ONLINE DEMO
Note: Here, you can use y instead of u but I prefer u to y.
Learn more about the modern Date-Time API from Trail: Date Time.

How to convert a date with time zone offset to another format

I tried reading a lot about the date formatting with time zone, but it doesn't make sense to me.
My DB shows this datetime: 2022-12-01 04:00:00.000 +08:00
My UI shows it as: Thu 01/12/2022 12:00
I need to compare between them to verify they are the same. I tried to convert the DB time like this:
String dbDate = "2022-12-01 04:00:00.000 +08:00";
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS XXX");
Date date = sf.parse(dbDate)
sf = new SimpleDateFormat("EEE dd/MM/yyy HH:mm");
String uiDate = sf.format(date);
The results received is a completely different date: 'Wed 30/11/2022 22:02'.
I don't understand the logic here and would appreciate help in converting it correctly.
As already commented by Yonatan Karp-Rudin, you can not compare a date-time with time-zone offset with another without time-zone offset. A clear way to compare the two date-times is to bring them to a single time-zone e.g. you can apply the same time-zone offset to the UI date-time as of the DB date-time.
In March 2014, java.time API supplanted the error-prone legacy date-time API. Since then, it has been strongly recommended to use this modern date-time API.
Demo using java.time API:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String dt1 = "2022-12-01 04:00:00.000 +08:00";
String dt2 = "Thu 01/12/2022 12:00";
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS XXX", Locale.ENGLISH);
OffsetDateTime odt1 = OffsetDateTime.parse(dt1, dtf1);
System.out.println(odt1);
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("EEE dd/MM/uuuu HH:mm", Locale.ENGLISH)
.withZone(odt1.getOffset());
OffsetDateTime odt2 = OffsetDateTime.parse(dt2, dtf2);
System.out.println(odt2);
System.out.println(odt1.equals(odt2));
}
}
Output:
2022-12-01T04:00+08:00
2022-12-01T12:00+08:00
false
Assuming both the date-times belong to the same time-zone offset, another way to compare them would be compare them without time-zone i.e. comparing their date-time part only (LocalDateTime).
Demo:
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String dt1 = "2022-12-01 04:00:00.000 +08:00";
String dt2 = "Thu 01/12/2022 12:00";
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS XXX", Locale.ENGLISH);
LocalDateTime ldt1 = OffsetDateTime.parse(dt1, dtf1).toLocalDateTime();
System.out.println(ldt1);
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("EEE dd/MM/uuuu HH:mm", Locale.ENGLISH);
LocalDateTime ldt2 = LocalDateTime.parse(dt2, dtf2);
System.out.println(ldt2);
System.out.println(ldt1.equals(ldt2));
}
}
Output:
2022-12-01T04:00
2022-12-01T12:00
false
The modern date-time API (java.time API) provides you with tools to do the same thing in many ways e.g. in the 1st demo, we could obtain the OffsetDateTime for your UI date-time string by parsing it into a LocalDateTime as shown in the 2nd demo and then using one of the ways shown in this answer where ZoneOffset offset = odt1.getOffset().
By the way, here is an example of how you format a date-time with time-zone offset to another format:
public class Main {
public static void main(String[] args) {
String dtDb = "2022-12-01 04:00:00.000 +08:00";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS XXX", Locale.ENGLISH);
OffsetDateTime odtDb = OffsetDateTime.parse(dtDb, parser);
System.out.println(odtDb);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE dd/MM/uuuu HH:mm", Locale.ENGLISH);
String strDtUi = odtDb.format(formatter);
System.out.println(strDtUi);
}
}
Output:
2022-12-01T04:00+08:00
Thu 01/12/2022 04:00
Learn more about the modern Date-Time API from Trail: Date Time.

2020-04-03 20:17:46 to "yyyy-MM-dd'T'HH:mm:ss" format

Is there any way in java(java.util.* or Joda api ) to convert "2020-04-03 20:17:46" to "yyyy-MM-dd'T'HH:mm:ss"
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.parse("2020-04-03 20:17:46")
its giving java.text.parseException always
Just for the case you are using Java 8 or above, make use of java.time.
See this simple example:
public static void main(String[] args) {
// example datetime
String datetime = "2020-04-03 20:17:46";
// create a formatter that parses datetimes of this pattern
DateTimeFormatter parserDtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// then parse the datetime with that formatter
LocalDateTime ldt = LocalDateTime.parse(datetime, parserDtf);
// in order to output the parsed datetime, use the default formatter (implicitly)
System.out.println(ldt);
// or format it in a totally different way
System.out.println(ldt.format(
DateTimeFormatter.ofPattern("EEE, dd. 'of' MMM 'at' hh-mm-ss a",
Locale.ENGLISH)
)
);
}
This outputs
2020-04-03T20:17:46
Fri, 03. of Apr at 08-17-46 PM
Please note that this doesn't consider any time zone or offset, it just represents a date and time consisting of the passed or parsed years, months, days, hours, minutes and seconds, nothing else.
Do not use Date/Time API from java.util.* as most of them are now outdated. Use java.time API instead.
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) throws IOException {
String strDatetime = "2020-04-03 20:17:46";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime parsedDate = LocalDateTime.parse(strDatetime, formatter);
System.out.println(parsedDate);
}
}
Output:
2020-04-03T20:17:46
Learn more about DateTimeFormatter at https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
Could this help you? http://tutorials.jenkov.com/java-internationalization/simpledateformat.html
First you need to parse the String with the old format, you will get a Date object. Then Create a new SimpleDateFormat with your new format, then you can format the Date object.
String dateString = "2020-04-03 20:17:46";
SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(dateString);
String formattedDate = output.format(date);
It do not work that way directly but if you still want to do it then, here is the process.
Create an object of SimpleDateFormat with pattern "yyyy-MM-dd HH:mm:ss")
use this to parse the string. Ultimately you are going to get date in both cases. Is there any specific reason for using T in pattern for dates which do not contain them?
Use LocalDateTime.
Timestamp timestamp = Timestamp.parse("2020-04-03 20:17:46");
LocalDateTime localDateTime = timestamp.toLocalDateTime();
System.out.println(localDateTime); // 2020-04-03T20:17:46

How to convert String e.g. "01/01/2019" to date in Java 8 [duplicate]

This question already has answers here:
Java string to date conversion
(17 answers)
Closed 4 years ago.
I'm trying to use Java 8's DateTimeFormatter to turn strings such as "17/01/2019" into dates of exactly the same format.
I'm currently using:
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/yyyy", Locale.ENGLISH);
LocalDateTime dExpCompletionDate = LocalDateTime.parse(sExpCompletionDate, format);
LocalDateTime dExpCommencementDate = LocalDateTime.parse(sExpCommencementDate, format);
and getting the error:
java.time.format.DateTimeParseException: Text '' could not be parsed at index 0
Which would suggest there's something wrong with my format.
Currently, I've tried using the default format as well as using LocalDate instead of LocalDateTime
You're trying to obtain LocalDateTime instead of LocalDate:
LocalDateTime dExpCompletionDate = LocalDateTime.parse(sExpCompletionDate, format);
Here is a small example with LocalDate:
public static void main(String[] args) {
String sExpCompletionDate = "17/01/2019";
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/yyyy", Locale.ENGLISH);
LocalDate dExpCompletionDate = LocalDate.parse(sExpCompletionDate, format);
// Converts LocalDate into LocalDateTime
LocalDateTime dExpCompletionDate2 = LocalDate.parse(sExpCompletionDate, format).atStartOfDay();
System.out.println(dExpCompletionDate);
System.out.println(dExpCompletionDate2);
}
Output:
2019-01-17
2019-01-17T00:00
Here is an example with LocalDateTime:
public static void main(String[] args) {
String sExpCompletionDate = "17/01/2019 14:22:11";
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss", Locale.ENGLISH);
LocalDateTime dExpCompletionDate = LocalDateTime.parse(sExpCompletionDate, format);
System.out.println(dExpCompletionDate);
}
Output:
2019-01-17T14:22:11
Because "dd/MM/yyyy" is date pattern, you can't parse to DateTime with it. What you can do is, parse to Date and then get StartOfDay as DateTime
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDateTime dExpCompletionDate = LocalDate.parse("01/01/2019", format).atStartOfDay();
Use SimpleDateFormat. Here is a working example:
import java.text.SimpleDateFormat;
import java.util.Date;
public class StringToDateExample1 {
public static void main(String[] args)throws Exception {
String sDate1="31/12/1998";
Date date1=new SimpleDateFormat("dd/MM/yyyy").parse(sDate1);
System.out.println("Date is : "+date1);
}
}
For a more comprehensive answer, refer to reply by BalusC.

Parse String timestamp to Instant throws Unsupported field: InstantSeconds

I am trying to convert a String into an Instant. Can you help me out?
I get following exception:
Caused by: java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: InstantSeconds
at java.time.format.Parsed.getLong(Parsed.java:203)
at java.time.Instant.from(Instant.java:373)
My code looks basically like this
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String timestamp = "2016-02-16 11:00:02";
TemporalAccessor temporalAccessor = formatter.parse(timestamp);
Instant result = Instant.from(temporalAccessor);
I am using Java 8 Update 72.
A simpler method is to add the default timezone to the formatter object when declaring it
final DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneId.systemDefault());
Instant result = Instant.from(formatter.parse(timestamp));
Here is how to get an Instant with a default time zone. Your String can not be parsed straight to Instant because timezone is missing. So you can always get the default one
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String timestamp = "2016-02-16 11:00:02";
TemporalAccessor temporalAccessor = formatter.parse(timestamp);
LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
Instant result = Instant.from(zonedDateTime);
I wrote such simple function to perform the conversion:
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.time.ZonedDateTime;
import java.time.Instant;
import java.sql.Timestamp;
public class SqlTimestampParser {
public static Timestamp parseTimestamp(String dateTime, String format) throws Exception {
if (format == null || format.trim().length() == 0) {
throw new Exception("No format defined!");
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
ZonedDateTime timed = ZonedDateTime.parse(dateTime, formatter);
timed.format(formatter);
Instant x = Instant.from(timed);
return Timestamp.from(x);
}
}
With sample usage:
SqlTimestampParser.parseTimestamp('2020-09-17 16:20:35.294000+00:00',"yyyy-MM-dd HH:mm:ss.SSSSSSXXX")
First convert your date into util date using date format as you don't have time zone in your input. Then you can convert that date into Instant date. This will give you date with accurate time.
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String timestamp = "2016-02-16 11:00:02";
Date xmlDate = dateFormat.parse(timestamp);
dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Instant instantXmlDate = Instant.parse(dateFormat.format(xmlDate));

Categories