I have input date and time "2021-05-03T15:46:09.354+08:00"
I want UTC format output - "2021-05-03T07:46:09.354Z"
Any Idea and suggestion
Input string fits an OffsetDateTime and output string fits an Instant, so:
Instant instant = OffsetDateTime.parse("2021-05-03T15:46:09.354+08:00").toInstant();
System.out.println(instant); // prints: 2021-05-03T07:46:09.354Z
You can also use ZonedDateTime and the result can be also be OffsetDateTime or ZonedDateTime.
ZonedDateTime inZoned = ZonedDateTime.parse("2021-05-03T15:46:09.354+08:00");
ZonedDateTime outZoned = inZoned.withZoneSameInstant(ZoneOffset.UTC);
System.out.println(inZoned + " -> " + outZoned);
// prints: 2021-05-03T15:46:09.354+08:00 -> 2021-05-03T07:46:09.354Z
OffsetDateTime inOffset = inZoned.toOffsetDateTime();
OffsetDateTime outOffset = inOffset.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(inOffset + " -> " + outOffset);
// prints: 2021-05-03T15:46:09.354+08:00 -> 2021-05-03T07:46:09.354Z
Dont have enough reputation to comment, but have you tried using the Instant class in Java? Link to javadoc. The parse() might be able to help, then you can call toString() on the Instant.
https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html
https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#parse-java.lang.CharSequence-
public static void main(String[] args) throws Exception
{
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter
.ofPattern("dd-MM-uuuu'T'HH:mm:ss:SSSXXXXX");
//Date string with offset information
String dateString = "03-08-2019T16:20:17:717+05:30";
System.out.println("input date: "+dateString);
//Instance with given offset
OffsetDateTime odtInstanceAtOffset = OffsetDateTime.parse(dateString, DATE_TIME_FORMATTER);
//Instance in UTC
OffsetDateTime odtInstanceAtUTC = odtInstanceAtOffset.withOffsetSameInstant(ZoneOffset.UTC);
//Formatting to string
String dateStringInUTC = odtInstanceAtUTC.format(DATE_TIME_FORMATTER);
//Convert OffsetDateTime to instant which is in UTC
System.out.println("expected date :"+odtInstanceAtOffset.toInstant());
}
ouput:
input date: 03-08-2019T16:20:17:717+05:30
expected date :2019-08-03T10:50:17.717Z
Related
When I try to convert OffsetDateTime to LocalDateTime from java.time, I expect the resulting LocalDateTime to be updated with the local time zone. So, If I have an OffsetDateTime of 2011-12-03T10:00:00Z, and my local timezone is UTC+2, I expect the LocalDateTime to be 2011-12-03T12:00:00, but I get instead 2011-12-03T10:00:00. I'm converting it with the method toLocalDateTime() that OffsetDateTime has. It seems that it only truncates the date, removing the offset part, without adjusting the time.
So I'm trying to figure out a way to get a LocalDateTime that represents the local date time taking into account the zone offset. Following the example, I would like to get 2011-12-03T12:00:00
LocalDateTime would give you the time of a wall clock of your OffsetDateTime. That's 10:00
You need to first convert to a ZonedDatedTime in your time zone
Like this
OffsetDateTime off = OffsetDateTime.of(2011,12,3,10,00,0,0, ZoneOffset.UTC);
ZonedDateTime zoned = off.atZoneSameInstant(ZoneId.of("Europe/Athens"));
LocalDateTime athensWallTime = zoned.toLocalDateTime();
System.out.println(athensWallTime);
I think what you are looking for is OffsetDateTime.atZoneSameInstant:
OffsetDateTime.parse("2011-12-03T10:00:00Z")
.atZoneSameInstant(ZoneId.systemDefault())
.toLocalDateTime()
OffsetDateTime#withOffsetSameInstant
If you need to convert an object of OffsetDateTime to an OffsetDateTime object with a different ZoneOffset, you can do so by using OffsetDateTime#withOffsetSameInstant.
Demo:
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class Main {
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.parse("2011-12-03T10:00:00Z");
OffsetDateTime odtWithOffsetTwoHours = odt.withOffsetSameInstant(ZoneOffset.of("+02:00"));
System.out.println(odtWithOffsetTwoHours);
LocalDateTime ldt = odtWithOffsetTwoHours.toLocalDateTime();
System.out.println(ldt);
}
}
Output:
2011-12-03T12:00+02:00
2011-12-03T12:00
ONLINE DEMO
I suggest you keep using OffsetDateTime because LocalDateTime, as the name suggests, throws away the useful timezone information. Nevertheless, LocalDateTime is useful in some scenarios as mentioned on this page.
If you are dealing with JDBC, check this answer and this answer.
Learn more about the modern Date-Time API from Trail: Date Time.
I think the most concise solution is
LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC)
Here is some code you can try :
public static void main(String[] args) {
OffsetDateTime offsetDT1 = OffsetDateTime.now();
System.out.println("OffsetDateTime1: " + offsetDT1);
OffsetDateTime offsetDT2 = OffsetDateTime.now(Clock.systemUTC());
System.out.println("OffsetDateTime2: " + offsetDT2);
OffsetDateTime offsetDT3 = OffsetDateTime.now(ZoneId.of("Asia/Jakarta"));
System.out.println("OffsetDateTime3: " + offsetDT3);
OffsetDateTime offsetDT4 = OffsetDateTime.of(1980, 4, 9, 20, 15, 45, 345875000, ZoneOffset.of("+07:00"));
System.out.println("OffsetDateTime4: " + offsetDT4);
OffsetDateTime offsetDT5 = OffsetDateTime.of(LocalDate.now(), LocalTime.of(15, 50, 25), ZoneOffset.of("+07:00"));
System.out.println("OffsetDateTime5: " + offsetDT5);
OffsetDateTime offsetDT6 = OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.of("+07:00"));
System.out.println("OffsetDateTime6: " + offsetDT6);
OffsetDateTime offsetDT7 = OffsetDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
System.out.println("OffsetDateTime7: " + offsetDT7);
OffsetDateTime offsetDT8 = OffsetDateTime.parse("2019-08-31T15:20:30+08:00");
System.out.println("OffsetDateTime8: " + offsetDT8);
OffsetDateTime offsetDT9 = OffsetDateTime.parse("1980-04-09T08:20:45+07:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME);
System.out.println("OffsetDateTime9: " + offsetDT9);
Output
OffsetDateTime1: 2019-08-31T23:49:05.629+08:00
OffsetDateTime2: 2019-08-31T15:49:05.630Z
OffsetDateTime3: 2019-08-31T22:49:05.630+07:00
OffsetDateTime4: 1980-04-09T20:15:45.345875+07:00
OffsetDateTime5: 2019-08-31T15:50:25+07:00
OffsetDateTime6: 2019-08-31T23:49:05.631+07:00
OffsetDateTime7: 2019-08-31T23:49:05.631+08:00
OffsetDateTime8: 2019-08-31T15:20:30+08:00
OffsetDateTime9: 1980-04-09T08:20:45+07:00
You can take a look on this website for more explaination or browse javadoc wbsite.
Getting a DateTimeParseExcpetion when trying to convert the String 2020-04-01T08:53:47.000+02:00 00:00
String date = "2020-04-01T08:53:47.000+02:00 00:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSz");
parsedDate = LocalDateTime.parse(date,formatter).toString();
System.out.println(parsedDate);
Your pattern is not the same as your String. Check the last part where is 000+02:00 00:00.
Your pattern is: SSSz
If you try this:
String date = "2020-04-01T08:53:47.000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
It will works because your date is like your pattern. Note that every number in the date is into pattern too.
But for your date there is an empty space what no make sense, so removing it, the code works perfectly.
String date = "2020-04-01T08:53:47.000+02:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSz");
Output:
2020-04-01T08:53:47
Note that z is the local time and means "zero hour offset" or "Zulu time" (UTC) and you can use Locale.
The 00:00 at the end of your date-time string doesn't make sense to me. Parse the date-time string after stripping that.
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 strDate = "2020-04-01T08:53:47.000+02:00 00:00";
strDate = strDate.substring(0, strDate.lastIndexOf(' '));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSz", Locale.ENGLISH);
LocalDateTime parsedDate = LocalDateTime.parse(strDate, formatter);
System.out.println(parsedDate);
OffsetDateTime odt = OffsetDateTime.parse(strDate);
System.out.println(odt);
System.out.println(odt.getOffset());
}
}
Output:
2020-04-01T08:53:47
2020-04-01T08:53:47+02:00
+02:00
Note: You can parse your date-time string (after striping 00:00 from the end of it) to OffsetDateTime in order to preserve the zone-offset information.
Use the built-in formatter
The built-in DateTimeFormatter.ISO_OFFSET_DATE_TIME matches the part of your string that we can understand. And it can parse just that part and ignore the rest.
String date = "2020-04-01T08:53:47.000+02:00 00:00";
ParsePosition pp = new ParsePosition(0);
OffsetDateTime odt = OffsetDateTime.from(
DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(date, pp));
System.out.println("Date and time: " + odt);
System.out.println("Unparsed text: " + date.substring(pp.getIndex()));
Output:
Date and time: 2020-04-01T08:53:47+02:00
Unparsed text: 00:00
Since your string contains an offset from UTC, OffsetDateTime is the correct class to parse into. If we used LocalDateTIme, the offset would be ignored, and we would end up not knowing at which offset the time was to be interpreted, that is, we could not know which point in time it was. With OffsetDateTime the point in time is unambiguous. If you want to convert to the time in your own time zone, convert to ZonedDateTime (still not LocalDateTime).
ZonedDateTime timeInMyTimeZone = odt.atZoneSameInstant(ZoneId.systemDefault());
System.out.println("Date and time: " + timeInMyTimeZone);
Example output:
Date and time: 2020-04-01T11:53:47+05:00[Asia/Aqtobe]
Links
Documentation links:
DateTimeFormatter.ISO_OFFSET_DATE_TIME.
The two-arg DateTimeFormatter.parse(CharSequence, ParsePosition) that I used.
i have data like this one
date what i got from timestamp utc are : 2020-06-29 05:31:58.153
LocalDateTime timestampasstring = message.getHeader().getUtcTimeStamp( SendingTime.FIELD);
Timestamp timestamp = Timestamp.from(timestampasstring.toInstant(ZoneOffset.UTC));
System.out.println(timestamp);
String timestampstrings = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp);
String timestampstrings2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(timestamp);
i need to get timestamp number like 2020-06-29 05:31:58
and convert it become unix timestamp like this one 1593408718
how to convert it ?
If your getUtcTimeStamp method is helpful enough to return a LocalDateTime, you're most of the way there. Convert to an Instant using ldt.atOffset(ZoneOffset.UTC) (your getUtcTimeStamp really should be doing this for you if it already knows it's in UTC), then just call toEpochSecond() (or toEpochMilli() if you want the milliseconds part, but you just showed whole seconds).
Having read your question, I assume your method message.getHeader().getUtcTimeStamp(SendingTime.FIELD) returns a String (not a LocalDateTime) representing a timestamp in UTC while being formatted either like 2020-06-29 05:31:58.153 or 2020-06-29 05:31:58.
Since you have (shown) differently formatted datetimes (respectively, datetimes with a different accuracy), you will have to take care of that by defining a suitable DateTimeFormatter using a pattern able to deal with optional milliseconds (yyyy-MM-dd HH:mm:ss[.SSS]).
You can use it as follows:
public static void main(String[] args) {
// receive the result from your message, this is just an example
String utcTimestamp = "2020-06-29 05:31:58";
// create a ZonedDateTime by parsing the String to a LocalDateTime and adding a time zone
ZonedDateTime zdt = LocalDateTime.parse(utcTimestamp,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]"))
.atZone(ZoneId.of("UTC"));
// then get the epoch milliseconds / unix timestamp
long millis = zdt.toInstant().toEpochMilli();
// and print the result
System.out.println(zdt + " ==> " + millis + " epoch millis");
}
The output of this is, of course, different for datetimes that are only equal down to seconds:
2020-06-29T05:31:58Z[UTC] ==> 1593408718000 epoch millis
2020-06-29T05:31:58.153Z[UTC] ==> 1593408718153 epoch millis
If you call long seconds = zdt.toEpochSeconds() instead of converting toInstant().toEpochMillis (and adjust the output a little) you will get the same value for both examples:
public static void main(String[] args) {
// receive the result from your message, this is just an example
String utcTimestamp = "2020-06-29 05:31:58.153";
// create a ZonedDateTime by parsing the String to a LocalDateTime and adding a time zone
ZonedDateTime zdt = LocalDateTime.parse(utcTimestamp,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]"))
.atZone(ZoneId.of("UTC"));
// then get the epoch seconds
long seconds = zdt.toEpochSecond();
// and print the result
System.out.println(zdt + "\t==>\t" + seconds + " epoch seconds");
}
Output:
2020-06-29T05:31:58Z[UTC] ==> 1593408718 epoch seconds
2020-06-29T05:31:58.153Z[UTC] ==> 1593408718 epoch seconds
If your method really returns a LocalDateTime, you could simply skip conversions and write
public static void main(String[] args) {
LocalDateTime utcDateTime = message.getHeader().getUtcTimeStamp(SendingTime.FIELD);
// then get the epoch seconds
long seconds = utcDateTime.atZone(ZoneId.of("UTC")).toEpochSecond();
// and print the result
System.out.println(utcDateTime + "\t==>\t" + seconds + " epoch seconds");
}
The other answers are fine. Here’s my variant. First declare a formatter for parsing:
private DateTimeFormatter timestampFormatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter();
Consider declaring the formatter static and/or final. With this formatter I’d do:
String timestampAsString = "2020-06-29 05:31:58.153";
OffsetDateTime dateTime = LocalDateTime
.parse(timestampAsString, timestampFormatter)
.atOffset(ZoneOffset.UTC);
long unixTimestamp = dateTime.toEpochSecond();
System.out.println(unixTimestamp);
Output is what you asked for:
1593408718
The nice thing about the formatter is that it accepts both 2020-06-29 05:31:58.153 and 2020-06-29 05:31:58, that is, time both with and without fraction of second, and with any fraction of from 1 up to 9 decimals. Reusing ISO_LOCAL_TIME in the formatter buys us this.
I'm trying to parse 2009-07-30T16:10:36+06:00 to a date using yyyy-MM-dd'T'HH:mm:ssXXXXX.
However the output I get appears to have not factored in the offset, as I get yyyy-MM-dd'T'HH:mm:ssXXXXX.
Any ideas what I'm missing?
final DateTimeFormatter iso8601Formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXXXX");
final ZonedDateTime zonedDateTime = ZonedDateTime.parse("2009-07-30T16:10:36+06:00", iso8601Formatter);
final String formatted = zonedDateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"));
System.out.println(formatted);
If my understanding is correct you should set the zone similar to withZoneSameInstant(ZoneId.of("UTC"))
final ZonedDateTime zonedDateTime = ZonedDateTime.parse("2009-07-30T16:10:36+06:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME);
System.out.println("Without ZoneId: " + zonedDateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")));
System.out.println("With ZoneId: " + zonedDateTime.withZoneSameInstant(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")));
Result
Without ZoneId: 30/07/2009 16:10:36
With ZoneId: 30/07/2009 10:10:36
OffsetDateTime odt = OffsetDateTime.parse("2009-07-30T16:10:36+06:00");
ZonedDateTime zdt = ZonedDateTime.ofInstant(odt.toInstant(), ZoneOffset.UTC);
// 2009-07-30T10:10:36Z
First you have no zoned date time, which would also depend on the country.
Then actually you want the Greenwich time, the UTC.
If you want the time in UTC (which is not clear from the question), then the other answers give you the correct result. Since there is no time zone (such as Europe/London Pacific/Rarotonga) in your data, there is no point in using a ZonedDateTime. OffsetDateTime is a better fit:
final OffsetDateTime dateTime = OffsetDateTime.parse("2009-07-30T16:10:36+06:00");
final OffsetDateTime utcDateTime = dateTime.withOffsetSameInstant(ZoneOffset.UTC);
final String formatted = utcDateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"));
System.out.println(formatted);
30/07/2009 10:10:36
In Java 8, I want to convert a datetime from UTC to ACST (UTC+9:30).
input -> 2014-09-14T17:00:00+00:00
output-> 2014-09-15 02:30:00
String isoDateTime = "2014-09-14T17:00:00+00:00";
LocalDateTime fromIsoDate = LocalDateTime.parse(isoDateTime, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
ZoneOffset offset = ZoneOffset.of("+09:30");
OffsetDateTime acst = OffsetDateTime.of(fromIsoDate, offset);
System.out.println(acst.toString()); // 2014-09-14T17:00+09:30
System.out.println(acst.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); // 2014-09-14T17:00:00+09:30
Why is the offset not performed?
Try:
String isoDateTime = "2014-09-14T17:00:00+00:00";
ZonedDateTime fromIsoDate = ZonedDateTime.parse(isoDateTime);
ZoneOffset offset = ZoneOffset.of("+09:30");
ZonedDateTime acst = fromIsoDate.withZoneSameInstant(offset);
System.out.println("Input: " + fromIsoDate);
System.out.println("Output: " + acst.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
Output:
Input: 2014-09-14T17:00Z
Output: 2014-09-15T02:30:00+09:30
Using OffsetDateTime
While it is generally better to use ZonedDateTime as shown above, you can perform the same conversion using OffsetDateTime as follows:
String isoDateTime = "2014-09-14T17:00:00+00:00";
OffsetDateTime fromIsoDate = OffsetDateTime.parse(isoDateTime);
ZoneOffset offset = ZoneOffset.of("+09:30");
OffsetDateTime acst = fromIsoDate.withOffsetSameInstant(offset);
Slight improvement on the above. Avoids hardcoding offset. Also, takes care of daylight savings.
public static LocalDateTime convertTo(LocalDateTime dateTime, String timeZone) {
ZoneId zone = ZoneId.of(timeZone);
ZonedDateTime zdt = dateTime.atZone(zone);
ZoneOffset offset = zdt.getOffset();
return dateTime.plus(offset.getTotalSeconds(), ChronoUnit.SECONDS);
}