Not able to convert UTC to local time - java

I am writing a Java Code.I am able to convert the local time to UTC.But I am facing the problem when I want to convert it back to local time.The steps I am doing-
Getting milliseconds of the present.(DONE)
Converting present milliseconds(millisSinceEpoch) to present local time.(DONE)
Converting present milliseconds(millisSinceEpoch) to UTC time.(DONE)
Converting UTC time to UTC milliseconds.(DONE)
Convert UTC milliseconds to UTC Time.(DONE)
Convert UTC milliseconds to local time(IST)(Facing the problem here.....Getting the same UTC time here.Why is it not converting to Local time?).There is an answer where multiple date objects are created,But here I am not creating multiple date Objects and working only on milliseconds.My Code-
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.TimeZone;
public class TimeApiClass {
public static void main(String args[]) throws ParseException {
ZonedDateTime currentZone = ZonedDateTime.now();
//Getting milliseconds of the present
Instant instant=currentZone.toInstant();
long millisSinceEpoch=instant.toEpochMilli();
System.out.println("Not Converted to UTC-(Milliseconds-in local)");
System.out.println(millisSinceEpoch); //Output1->1579788244731
//Converting present milliseconds(millisSinceEpoch) to present local time
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS ");
String str3=sdf3.format(new Date(millisSinceEpoch));
System.out.println("Local Time-Not Converted to UTC-(Present local time)");
System.out.println(str3); //2020/01/23 19:34:04.731
//Converting present milliseconds(millisSinceEpoch) to UTC time
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS ");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String str=sdf.format(new Date(millisSinceEpoch));
System.out.println("UTC time-Local time Converted to UTC(unrequired time format)-");
System.out.println(str);// str contains 2020/01/22 13:22:55 UTC //Output3 ->2020/01/23 14:04:04.731
System.out.println("-----------------------------------------------------------------------------------------");
//Converting UTC time to UTC milliseconds
String myDate = str; // myDate and str contains 2020/01/22 10:08:42
SimpleDateFormat sdff = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS ");
Date date = sdff.parse(myDate);
long millis = date.getTime();
System.out.println("Converted to milliseconds(Now its in required format in UTC milliseconds)");
System.out.println(millis); //Output4 ->1579749867000
//Convert UTC milliseconds to UTC Time
DateFormat simple = new SimpleDateFormat(" yyyy/MM/dd HH:mm:ss.SSS");
Date result=new Date(millis);
System.out.println("Converting UTC milliseconds back to date/time format-");
System.out.println(simple.format(result));
//Convert UTC milliseconds to local time(IST)
Date dateee=new Date(millis); //Facing the problem here.....Getting the same UTC time here.Why is it not converting to Local time?
DateFormat format=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
format.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
System.out.println("lllllllllllllllllllllllll");
System.out.println(format.format(dateee));
//Converting UTC time to IST time
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS ");
sdf2.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
String istTime=sdf2.format(new Date(millis));
System.out.println("Now converting UTC millis to IST format->");
System.out.println(istTime); //Output5 ->2020/01/23 08:54:27 IST
//Converting IST time to milliseconds,here I am facing the problem.My output has to give the local milliseconds as I am passing ISTtime here,but its giving me UTC milliseconds,Which I dont want.
Date date66=sdf2.parse(istTime);
long finalMillis=date66.getTime();
System.out.println("Now converting IST to IST milliseconds:");
System.out.println(finalMillis); //Output6 ->1579749867000
}
}
//1579613838087

tl;dr
Convert a ZonedDateTime into a different time zone by ZonedDateTime.withZoneSameInstant(ZoneId)
You are not well advised to use java.util.SimpleDateFormat for operations on dates and times and your code shows partial use of java.time, which means you can just switch to java.time entirely. For formatting, use a java.time.format.DateTimeFormatter.
See this example:
public static void main(String[] args) {
// get the current instant
Instant instant = Instant.now();
// and convert it to a datetime object representing date and time in UTC
ZonedDateTime ofInstant = ZonedDateTime.ofInstant(instant, ZoneId.of("UTC"));
// print it
System.out.println("Now from Instant in UTC:\t"
+ ofInstant.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
// you can have a shorter way: current moment in your system's time zone
ZonedDateTime nowHere = ZonedDateTime.now();
// or in UTC
ZonedDateTime utcNow = ZonedDateTime.now(ZoneId.of("UTC"));
// print them both
System.out.println("Now in my (system's) time zone:\t"
+ nowHere.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
System.out.println("Now in UTC:\t\t\t"
+ utcNow.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
// then format the UTC datetime back to the one your system has
ZonedDateTime backFromUtc = utcNow.withZoneSameInstant(ZoneId.systemDefault());
// and print that one, too
System.out.println("Back from UTC:\t\t\t"
+ backFromUtc.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
}
The output something like:
Now from Instant in UTC: 2020-01-23T15:44:11.921Z[UTC]
Now in my (system's) time zone: 2020-01-23T16:44:12.091+01:00[Europe/Berlin]
Now in UTC: 2020-01-23T15:44:12.091Z[UTC]
Back from UTC: 2020-01-23T16:50:52.194+01:00[Europe/Berlin]

Why is it not converting to Local time?
Where it goes wrong for you: The string myDate is in UTC, but (1) there is no indication of UTC in the string, and (2) you are parsing it using the formatter sdff, but this formatter is not using UTC (it is using your default time zone, India Standard Time). Therefore you are getting a wrong result from parsing.
There may be another misunderstanding: The epoch is one specific point in time regardless of time zone. Therefore milliseconds since the epoch are the same in all time zones. So the first sign of a problem is probably when your program is printing two different millisecond values. If the millisecond values were supposed to denote the same point in time, you should see the same value both times.
All of this said, deHaar is correct in the other answer that you should stay away from all of DateFormat, SimpleDateFormat, Date and TimeZone. All of those classes are poorly designed and long outdated. I think that your use of the mentioned classes have contributed quite much to making your code more complicated than it had needed to be.
Edit:
So you are telling me to not use DateFormat,SimpleDateFormat and
TimeZone.So can you please suggest as to which class I should be
ideally using?
You are already on the good track when using Instant and ZonedDateTime from java.time, the modern Java date and time API. This API offers all the functionality you need and is so much nicer to work with, so I suggest that you stick to it. Other java.time classes that you will probably find useful include ZoneId (instead of TimeZone) and DateTimeFormatter (instead of SimpleDateFormat and DateFormat). For more see the tutorial and/or the documentation. I will add links at the bottom later.
To parse a UTC string into milliseconds since the epoch:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss.SSS");
String utcString = "2020/01/22 13:22:55.731";
long millisSinceEpoch = LocalDateTime.parse(utcString, formatter)
.atOffset(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
System.out.println(millisSinceEpoch);
1579699375731
Or if your real goal was to convert it to local time in India:
ZoneId indiaStandardTime = ZoneId.of("Asia/Kolkata");
ZonedDateTime timeInIndia = LocalDateTime.parse(utcString, formatter)
.atOffset(ZoneOffset.UTC)
.atZoneSameInstant(indiaStandardTime);
System.out.println(timeInIndia);
2020-01-22T18:52:55.731+05:30[Asia/Kolkata]
I am first telling Java to interpret the string in UTC, next to convert it to IST.
Links
Oracle tutorial: Date Time explaining how to use java.time.
java.time package documentation

Related

Java convert ISO 8601 string to Date ignoring offset

I have a string coming to me in the following format "yyyy-MM-dd'T'HH:mm:ssZ" ex: 2020-09-09T09:58:00+0000" offset is UTC.
I need the string to be converted to a Date object without the offset "+0000" being applied, but I keep getting a different time when running my code:
DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
Date date = isoFormat.parseDateTime("2020-09-09T09:58:00+0000").toDate();
// Wed Sep 09 05:58:00 EDT 2020
As you can see above the date has changed.
Instead, I would like to keep the same date and time like: Wed Sep 09 09:58:00, so I can convert this Date object to a String with "yyyy-MM-dd", "HH:mm:ss", and "yyyy-MM-dd'T'HH:mm:ss" format respectively.
The first and most important part of the answer is: don’t convert to an old-fashioned Date. Either stick to Joda-Time or migrate to java.time, the modern Java date and time API, as already covered in the good answer by Arvind Kumar Avinash.
Since you are already using Joda-Time, I am showing you a Joda-Time solution. The trick for persuading the formatter into keeping the time and offset from the string parsed is withOffsetParsed().
DateTimeFormatter isoFormat
= ISODateTimeFormat.dateTimeParser().withOffsetParsed();
String incomingString = "2020-09-09T09:58:00+0000";
DateTime dateTime = isoFormat.parseDateTime(incomingString);
However! If I have guessed correctly that you want to store date and time in UTC (a recommended practice), better than withOffsetParsed() is to specify UTC on the parser:
DateTimeFormatter isoFormat
= ISODateTimeFormat.dateTimeParser().withZoneUTC();
Now you will also get the correct time if one day a string with a non-zero UTC offset comes in.
In any case we may now format your obtained DateTime into the strings you requested.
String dateString = dateTime.toString(ISODateTimeFormat.date());
System.out.println(dateString);
String timeString = dateTime.toString(ISODateTimeFormat.hourMinuteSecond());
System.out.println(timeString);
String dateTimeString = dateTime.toString(ISODateTimeFormat.dateHourMinuteSecond());
System.out.println(dateTimeString);
Output:
2020-09-09
09:58:00
2020-09-09T09:58:00
What was wrong with using Date? First, the Date class is poorly designed and long outdated. Second, a Date was just a point in time, it didn’t have a concept of date and time of day (they tried building that into it in Java 1.0, but gave up and deprecated it in Java 1.1 in 1997). So a Date cannot hold the date and time of day in UTC for you.
What happened in your code was that you got a Date representing the correct point in time. Only when you printed that Date you were implicitly invoking its toString method. Date.toString() confusingly grabs the JVM’s time zone setting (in your case apparently North American Eastern Time) and uses it for rendering the string to be returned. So in your case the point in time was rendered as Wed Sep 09 05:58:00 EDT 2020.
I recommend you do it with the modern java.time date-time API and the corresponding formatting API (package, java.time.format). Learn more about the modern date-time API from Trail: Date Time.
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// The given date-time string
String strDateTime = "2020-09-09T09:58:00+0000";
// Define the formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ");
// Parse the given date-time string into OffsetDateTime
OffsetDateTime odt = OffsetDateTime.parse(strDateTime, formatter);
// Output OffsetDateTime in the default format
System.out.println(odt);
// Print OffsetDateTime using the defined formatter
String formatted = formatter.format(odt);
System.out.println(formatted);
}
}
Output:
2020-09-09T09:58Z
2020-09-09T09:58:00+0000
Note: java.util.Date does not represent a Date/Time object. It simply represents the no. of milliseconds from the epoch of 1970-01-01T00:00:00Z. It does not have any time-zone or zone-offset information. When you print it, Java prints the string obtained by applying the time-zone of your JVM. I suggest you stop using java.util.Date and switch to the modern date-time API.
Using joda date-time API, you can do it as follows:
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
public class Main {
public static void main(String[] args) {
// The given date-time string
String strDateTime = "2020-09-09T09:58:00+0000";
// Define the formatter
DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
DateTime dateTime = isoFormat.parseDateTime("2020-09-09T09:58:00+0000");
// Display DateTime in the default format
System.out.println(dateTime);
// Define formatter for ouput
DateTimeFormatter outputFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZoneUTC();
// Display DateTime in the defined output format
String formatted = outputFormat.print(dateTime);
System.out.println(formatted);
}
}
Output:
2020-09-09T10:58:00.000+01:00
2020-09-09T09:58:00+0000

Java date with the format : YYYYMMDDHHMMss.000Z as GMT

I need to get today’s date at midnight in my time zone in the format YYYYMMDDHHMMss.000Z as date and time in GMT.
I'm interested in the date, not the time of day.
In my system when I have got a date: 20201001220000.000Z it is a day 20201003 as summertime for GMT. I am asking this question because I need to compare the 20201001220000.000Z with today’s date.
I need to get the date ( TODAY midnight) in format yyyyMMddHHmmss.SSSZ. TODAY midnight 20201004 in my system is: 20201003220000.000Z this date will be compared with other dates e.g 20201002220000.000Z. The problem is that I can't get midnight.
java.time
Edit:
I tend to understand that you want to format today’s date into your format for comparison with other date-time strings in UTC (GMT) in the same format. For comparing dates and times I suggest that you compare date-time objects, not strings. So the options are two:
Parse the existing string, convert it to a date in your time zone and compare it to today’s date.
Parse your existing string into a point in time. Compare to the start of today’s date.
Let’s see both options in code.
1. Convert to date and compare dates:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SSSX");
ZoneId zone = ZoneId.systemDefault();
LocalDate today = LocalDate.now(zone);
String gmtString = "20201001220000.000Z";
LocalDate dateFromGmtString = formatter.parse(gmtString, Instant::from)
.atZone(zone)
.toLocalDate();
if (dateFromGmtString.isAfter(today)) {
System.out.println(gmtString + " is in the future");
} else if (dateFromGmtString.isBefore(today)) {
System.out.println(gmtString + " was on a past date");
} else {
System.out.println(gmtString + " is today");
}
Output:
20201001220000.000Z was on a past date
2. Find start of today’s date and compare times
Instant startOfDay = LocalDate.now(zone).atStartOfDay(zone).toInstant();
String gmtString = "20201001220000.000Z";
Instant timeFromGmtString = formatter.parse(gmtString, Instant::from);
if (timeFromGmtString.isBefore(startOfDay)) {
System.out.println(gmtString + " was on a past date");
} else {
System.out.println(gmtString + " is today or later");
}
20201001220000.000Z was on a past date
Original answer
You may be after the following. I recommend that you use java.time, the modern Java date and time API, for your date and time work.
DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SSSX");
String gmtString = "20201001220000.000Z";
Instant instant = sourceFormatter.parse(gmtString, Instant::from);
LocalDate date = instant.atZone(ZoneId.systemDefault()).toLocalDate();
String dayString = date.format(DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(dayString);
When I run the code in Europe/Warsaw time zone, the output is:
20201002
So the date has been converted from October 1 GMT to October 2 in Poland.
Edit:
… How can I get midnight?
To get the start of the day (usually 00:00):
ZonedDateTime startOfDay = time.atZone(ZoneId.systemDefault())
.truncatedTo(ChronoUnit.DAYS);
System.out.println(startOfDay);
2020-10-02T00:00+02:00[Europe/Warsaw]
Link: Oracle tutorial: Date Time explaining how to use java.time.
Try this.
String format = "yyyy-MM-dd HH:mm:ss.SSS O";
ZonedDateTime zdt = ZonedDateTime.now().withZoneSameInstant(ZoneId.of("GMT"));
System.out.println(zdt.format(DateTimeFormatter.ofPattern(format)));
Prints a US East coast time as
2020-10-03 14:47:18.809 GMT
You can delete the spaces, dashes and colons as desired. But do not use Date or related formatters as they are outdated. Use the classes from the java.time package.
You can do it as follows:
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// Today
LocalDate today = LocalDate.now();
// Midnight in the JVM's default time-zone
ZonedDateTime zdt = today.atStartOfDay(ZoneId.systemDefault());
// Printing zdt in its default format i.e. value returned by zdt.toString()
System.out.println(zdt);
// Printing zdt in your custom format
DateTimeFormatter customFormat = DateTimeFormatter.ofPattern("yyyyMMddHHmmss.SSSZ");
String dateTimeStrCustom = zdt.format(customFormat);
System.out.println(dateTimeStrCustom);
}
}
Output:
2020-10-04T00:00+01:00[Europe/London]
20201004000000.000+0100

Get 1 year back dateTime from current dateTime in yyyy-MM-dd HH:mm:ss.SSS format

I need to get the datetime of 1 year back considering the current datetime. The format needed to be in "yyyy-MM-dd HH:mm:ss.SSS"
ex : 2019-08-13 12:00:14.326
I tried following. But getting an error.
LocalDate now = LocalDate.now();
LocalDate localDate = LocalDate.parse(now.toString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")).minusYears(1);
Below Exception returned:
DateTimeParseException: Text '2020-08-13' could not be parsed
What's the best way to do this in Java 8+ ?
A LocalDate does not hold any information about hours, minutes, seconds or any unit below, instead, it holds information about year, month and day. By calling LocalDate.now() you are getting the date of today (the day of code execution).
If you need the time as well, use a LocalDateTime, which has a method now(), too, and actually consists of a LocalDate and a LocalTime.
Your error message tells you that the content of a LocalDate cannot be formatted using the given pattern (-String) "yyyy-MM-dd HH:mm:ss.SSS" because that pattern requires values for hours (HH), minutes (mm), seconds (ss) and milliseconds (SSS are fraction of seconds and three of them make it be milliseconds).
For parsing Strings or formatting datetimes, a LocalDateTime may be suitable but if you want to reliably add or subtract a year or any other amount of time, you'd rather use a class that considers time zones, offsets and daylight saving like ZonedDateTime or OffsetDateTime...
The LocalDate is the wrong class for your requirement as it does not hold the time information. You can use LocalDateTime but I suggest you use OffsetDateTime or ZonedDateTime so that you can get the flexibility of using the Zone Offset and Zone ID. Check https://docs.oracle.com/javase/tutorial/datetime/iso/overview.html for an overview of date-time classes.
Also, keep in mind that a date or time or date-time object is an object that just holds the information about date/time; it doesn't hold any information about formatting and therefore no matter what you do when you print their objects, you will always get the output what their toString() methods return. In order to format these classes or in other words, to get a string representing a custom format of these objects, you have formatting API (e.g. the modern DateTimeFormatter or legacy SimpleDateFormat) at your disposal.
A sample code:
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// Get the current date & time at UTC
OffsetDateTime odtNow = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println("Now at UTC: " + odtNow);
// Get the date & time one year ago from now at UTC
OffsetDateTime odtOneYearAgo = odtNow.minusYears(1);
System.out.println("One year ago at UTC: " + odtNow);
// Define a formatter for the output in the desired pattern
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
// Format the date & time using your defined formatter
String formattedDateTimeOneYearAgo = formatter.format(odtOneYearAgo);
System.out.println("Date Time in the pattern, yyyy-MM-dd HH:mm:ss.SSS: " + formattedDateTimeOneYearAgo);
}
}
Output:
Now at UTC: 2020-08-13T08:50:36.277895Z
One year ago at UTC: 2020-08-13T08:50:36.277895Z
Date Time in the pattern, yyyy-MM-dd HH:mm:ss.SSS: 2019-08-13 08:50:36.277
May not be the best way, but this will do it
LocalDateTime date = LocalDateTime.now().minusYears(1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println(date.format(formatter));
You say you want date+time from 1 year back, but you give it only a date (LocalDate). If you just want the date, all you need to do is:
LocalDate now = LocalDate.now();
LocalDate then = now.minusYears(1);
And if you want the timestamp also, then:
LocalDateTime now = LocalDateTime.now();
LocalDateTime then = now.minusYears(1);
And so on for other objects.
As mentioned you should use LocalDateTime instead of LocalDate.
Your exception was thrown because your input String is in ISO_DATE_TIME format
Java Doc
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
String now = dateTimeFormatter.format(LocalDateTime.now());
LocalDateTime localDate = LocalDateTime.parse(now, dateTimeFormatter);

Convert YYYY-MM-DDThh:mm:ssTZD format date string to local time

In my spring boot application I have to convert ISO 8601 datetime to localdatetime without using JODA. Currently what I am doing is
String receivedDateTime = "2019-11-13T00:11:08+05:00";
ZonedDateTime zonedDateTime = ZonedDateTime.parse(receivedDateTime);
DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = new Date();
try {
date = utcFormat.parse(zonedDateTime.toString());
} catch (ParseException e) {
e.printStackTrace();
}
When I am using receivedDateTime with +00:00 like "2019-11-13T00:11:08+00:00" then it does not give any parsing error but not converting either. When I use +01:00 at the end then it also gives the parsing error.
UPDATE: 1
As per #Deadpool answer, I am using it like
String receivedDateTime = "2019-11-13T00:11:08+05:00";
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HHMM", "0000").optionalEnd()
.toFormatter();
OffsetDateTime dt = OffsetDateTime.parse(receivedDateTime, formatter);
LocalDateTime ldt = dt.toLocalDateTime();
System.out.println(ldt);
and the the value of ldt it print is 2019-11-13T00:11:08.
UPDATE 2:
I tried using C# the same example and it gives me this date time {2019-11-12 11:11:08 AM}, which looks correct as the input time GMT +5 Hours and local time is EST America. So, when it converted it then it went back to 12th of Nov. Here is the code
var timeString = "2019-11-13T00:11:08+05:00";
DateTime d2 = DateTime.Parse(timeString, null, System.Globalization.DateTimeStyles.RoundtripKind);
Console.WriteLine("Hello World!" + d2);
UPDATE 3: So it boils down to following solution input String "2019-11-13T06:01:41+00:00" and output is local date "2019-11-13T00:01:41" Where system defauld ZoneId is "America/Chicago" which is -06:00 GMT
private LocalDateTime convertUtcStringToLocalDateTime(String UtcDateTime) {
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HHMM", "0000").optionalEnd()
.toFormatter();
OffsetDateTime dateTime = OffsetDateTime.parse(UtcDateTime, formatter);
return dateTime.atZoneSameInstant(ZoneId.of(ZoneId.systemDefault().getId())).toLocalDateTime();
}
Using java.time alone this is simpler than you seem to think:
String receivedDateTime = "2019-11-13T00:11:08+05:00";
OffsetDateTime parsedDateTime = OffsetDateTime.parse(receivedDateTime);
ZonedDateTime dateTimeInMyTimeZone
= parsedDateTime.atZoneSameInstant(ZoneId.systemDefault());
System.out.println(dateTimeInMyTimeZone);
When I ran this in America/Toronto time zone, the output was:
2019-11-12T14:11:08-05:00[America/Toronto]
Since your string contains an offset, +05:00, and no time zone, like Asia/Karachi, use an OffsetDateTime for parsing it. Then convert to your local time zone using the atZoneSameInstant method. Even though you asked for your local time, don’t be fooled into using LocalDateTime. That class represent a date and time without any time zone, which is not what you need (and seldom needed at all).
Fortunately it’s easy to avoid the old classes SimpleDateFormat, DateFormat, TimeZone and Date. They were always poorly designed, the first two in particular are notoriously troublesome. They are all long outdated now. Instead get all the functionality we dream of from java.time, the modern Java date and time API.
What happened in your code?
Don’t use 'Z' in a format pattern string (and I repeat, don’t use SimpleDateFormat).
No matter if you use ZonedDateTime or OffsetDateTime, when you use toString with offset zero (as parsed from +00:00), the offset is printed as Z, which matches the 'Z' in your format pattern string, so your second parsing works. Only parsing once, converting back to string and parsing again is needlessly complicated. Worse when the original offset was +01:00 or +05:00. These are rendered the same again from toString, so don’t match 'Z', which caused your ParseException. Never use 'Z' in a format pattern string. Z denotes an offset of zero and needs to be parsed as an offset for you to get the correct result.
By using DateTimeFormatter you can customize the date format with different offset format by making them optional
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HHMM", "0000").optionalEnd()
.toFormatter();
And the use the OffsetDateTime to parse string representing with offset
A date-time with an offset from UTC/Greenwich in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00.
OffsetDateTime dateTime = OffsetDateTime.parse("2019-11-13T00:11:08+0000", formatter);
OffsetDateTime dateTime = OffsetDateTime.parse("2019-11-13T00:11:08+05:00", formatter);
If you want to convert it into local time zone time LocalDateTime then use atZoneWithSameInstant()
LocalDateTime local = dateTime.atZoneSameInstant(ZoneId.of("America/New_York")).toLocalDateTime()
Note : Don't use SimpleDateFormat and util.Date which are legacy old framework

How can I convert a Timestamp into either Date or DateTime object?

I'm retrieving a timestamp object from a database using ResultSet.getTimestamp(), but I'd like an easy way to get the date in the format of MM/DD/YYYY and the time in a format of HH:MM xx. I was tinkering around, it it looks as though I can do such by making use of the Date and/or DateTime objects within Java. Is that the best way to go, or do I even need to convert the timestamp to accomplish this? Any recommendations would be helpful.
....
while(resultSet.next()) {
Timestamp dtStart = resultSet.getTimestamp("dtStart");
Timestamp dtEnd = resultSet.getTimestamp("dtEnd");
// I would like to then have the date and time
// converted into the formats mentioned...
....
}
....
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTest {
public static void main(String[] args) {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
Date date = new Date(timestamp.getTime());
// S is the millisecond
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd/yyyy' 'HH:mm:ss:S");
System.out.println(simpleDateFormat.format(timestamp));
System.out.println(simpleDateFormat.format(date));
}
}
java.sql.Timestamp is a subclass of java.util.Date. So, just upcast it.
Date dtStart = resultSet.getTimestamp("dtStart");
Date dtEnd = resultSet.getTimestamp("dtEnd");
Using SimpleDateFormat and creating Joda DateTime should be straightforward from this point on.
java.time
Modern answer: use java.time, the modern Java date and time API, for your date and time work. Back in 2011 it was right to use the Timestamp class, but since JDBC 4.2 it is no longer advised.
For your work we need a time zone and a couple of formatters. We may as well declare them static:
static ZoneId zone = ZoneId.of("America/Marigot");
static DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM/dd/uuuu");
static DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm xx");
Now the code could be for example:
while(resultSet.next()) {
ZonedDateTime dtStart = resultSet.getObject("dtStart", OffsetDateTime.class)
.atZoneSameInstant(zone);
// I would like to then have the date and time
// converted into the formats mentioned...
String dateFormatted = dtStart.format(dateFormatter);
String timeFormatted = dtStart.format(timeFormatter);
System.out.format("Date: %s; time: %s%n", dateFormatted, timeFormatted);
}
Example output (using the time your question was asked):
Date: 09/20/2011; time: 18:13 -0400
In your database timestamp with time zone is recommended for timestamps. If this is what you’ve got, retrieve an OffsetDateTime as I am doing in the code. I am also converting the retrieved value to the user’s time zone before formatting date and time separately. As time zone I supplied America/Marigot as an example, please supply your own. You may also leave out the time zone conversion if you don’t want any, of course.
If the datatype in SQL is a mere timestamp without time zone, retrieve a LocalDateTime instead. For example:
ZonedDateTime dtStart = resultSet.getObject("dtStart", LocalDateTime.class)
.atZone(zone);
No matter the details I trust you to do similarly for dtEnd.
I wasn’t sure what you meant by the xx in HH:MM xx. I just left it in the format pattern string, which yields the UTC offset in hours and minutes without colon.
Link: Oracle tutorial: Date Time explaining how to use java.time.
You can also get DateTime object from timestamp, including your current daylight saving time:
public DateTime getDateTimeFromTimestamp(Long value) {
TimeZone timeZone = TimeZone.getDefault();
long offset = timeZone.getOffset(value);
if (offset < 0) {
value -= offset;
} else {
value += offset;
}
return new DateTime(value);
}
LocalDateTime dtStart = rs.getTimestamp("dtStart").toLocalDateTime();
Converts this Timestamp object to a code LocalDateTime.
The conversion creates a code LocalDateTime that represents the
same year, month, day of month, hours, minutes, seconds and nanos
date-time value as this code Timestamp in the local time zone.
since 1.8

Categories

Resources