This question already has answers here:
Calendar returns date in wrong time zone
(5 answers)
Getting the current time millis from device and converting it into a new date with different timezone [duplicate]
(2 answers)
DateFormat parse - not return date in UTC
(1 answer)
Closed 4 years ago.
We are converting database date into required user timezone. But if we format using jodatime in string format we are getting correct date and if we parse string to get date object we are getting wrong time. Here is my code. I tried jodatime parser and java date
public class Test {
public static void main(String[] args) {
String dateF = "01/19/2019 at 07:35 PM (UTC)";
String dateFormat = "MM/dd/yyyy 'at' hh:mm a (zzz)";
long time = 1603305000;
String timeZone = "Etc/UTC";
Locale locale=new Locale("en", "US");
DateTimeFormatter dateFormatter = null;
if (locale.equals(Locale.FRENCH)) {
dateFormatter = DateTimeFormat.forPattern(dateFormat).withLocale(locale);
} else {
dateFormatter = DateTimeFormat.forPattern(dateFormat).withLocale(null);
}
if (true) {
dateFormatter = dateFormatter.withZone(DateTimeZone.forID(timeZone));
}
// Old Logic using Java Time
DateFormat format3 = new SimpleDateFormat(dateFormat, locale);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(time);
if(true)
format3.setTimeZone(TimeZone.getTimeZone(timeZone));
DateTime jodatime = new DateTime(time);
try {
System.out.println(dateFormatter.print(jodatime));
System.out.println("timezone converted Date : " + format3.parse(dateFormatter.print(jodatime)));
System.out.println("dateFormatter.parseDateTime converted Date : " + dateFormatter.parseDateTime(dateFormatter.print(jodatime)).toDate());
} catch (Exception e) {
System.out.println(e);
}
}
}
Correct date in Formatted string 01/19/1970 at 01:21 PM (UTC)
We are getting a wrong result after parsing
timezone converted Date : Mon Jan 19 18:51:00 IST 1970
dateFormatter.parseDateTime converted Date : Mon Jan 19 18:51:00 IST 1970
Correct date in Formatted Date : Mon Jan 19 01:21:00 UTC 1970
Avoid legacy date-time classes
You are using terrible old classes bundled with the earliest versions of Java. These have been supplanted entirely by the modern java.time classes.
You are also apparently mixing those legacy classes with classes from the Joda-Time library. Firstly, that mixing is ill-advised. Secondly, Joda-Time is now in maintenance-mode, with its creators advising migration to java.time. Actually, both Joda-Time and java.time projects are led by the same man, Stephen Colebourne, with the first project having been the inspiration and education for the second.
Smart objects, not dumb strings
We are converting database date
Then avoid all the string manipulations you are doing.
As of JDBC 4.2, you can directly exchange java.time objects with your database. For a moment, meaning a column of a type akin to the SQL-standard TIMESTAMP WITH TIME ZONE, use OffsetDateTime class.
myPreparedStatement.setObject( … , myOffsetDateTime ) ;
…and…
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Most databases store moments in UTC. You may want to adjust into a time zone for presentation to users. Apply a ZoneId to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
Generate text in a certain format by using DateTimeFormatter object. Either specify a custom formatting pattern or automatically localize by calling ofLocalized… methods.
All of this has been covered many many many times on Stack Overflow already. Search to learn more.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Related
I am calling a rest web service that accepts Date. On client side, i have calling this service using JDK 8 OffsetDateTime Class.
Value that is going from my client side : 2018-07-01T05:30+05:30
Value that is accepted by Service : 2018-07-01T08:00:00.000+0000
Below is the code:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(ZoneId.of("UTC")));
cal.set(2018, 05, 31);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.HOUR_OF_DAY, 0);
OffsetDateTime offsetDateTime = OffsetDateTime.ofInstant(cal.getTime().toInstant(), ZoneId.systemDefault());
Value of offsetDateTime that is coming with above code is 2018-07-01T05:30+05:30.
I am in IST time zone.
Can someone help as to what needs to be done to change date to 2018-07-01T08:00:00.000+0000.
tl;dr
If you want 8 AM on first day of July at UTC…
OffsetDateTime.of(
2018 , 7 , 1 , // Date (year, month 1-12 is Jan-Dec, day-of-month)
8 , 0 , 0 , 0 , // Time (hour, minute, second, nano)
ZoneOffset.UTC // Offset-from-UTC (0 = UTC)
) // Returns a `OffsetDateTime` object.
.format( // Generates a `String` object with text representing the value of the `OffsetDateTime` object.
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSZ" , Locale.US )
) // Returns a `String` object.
2018-07-01T08:00:00.000+0000
Avoid legacy date-time classes
Never use Calendar or Date classes. They were completely supplanted by the modern java.time classes such as OffsetDateTime. You are mixing the legacy classes with the modern, and that makes no sense.
java.time
Your Question is not clear about what are your inputs and what are your outputs versus your expectations.
If you goal is 8 AM on July 1 in UTC:
LocalDate ld = LocalDate.of( 2018 , Month.JULY , 1 ) ;
LocalTime lt = LocalTime.of( 8 , 0 ) ;
OffsetDateTime odt = OffsetDateTime.of( ld , lt , ZoneOffset.UTC ) ;
odt.toString(): 2018-07-01T08:00Z
That string format complies with ISO 8061 standard. If your destination refuses that input and accepts only 2018-07-01T08:00:00.000+0000, then we must defining a formatting pattern.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSZ" , Locale.US );
String output = odt.format( f );
2018-07-01T08:00:00.000+0000
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
i think the below code will work
public static Date ConvertToGMT() {
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date utc = new Date(dateFormat.format(date));
return utc;
}
You can do it like so,
offsetDateTime.atZoneSameInstant(ZoneId.of("Asia/Kolkata"))
Update
If you need an instance of OffsetDateTime here it is.
offsetDateTime.atZoneSameInstant(ZoneId.of("Asia/Kolkata")).toOffsetDateTime();
It’s not the answer you asked for, but it may be the answer you prefer in the end: Check once more whether the service you are calling accepts the format that you are already giving it. Both formats conform with ISO 8601, so it seems that the service accepts this standard format. If so, it should accept yours too.
In any case, use OffsetDateTime and the other classes from java.time exclusively and avoid the old and outdated Calendar and TimeZone classes. Basil Bourque’s answer shows the good solution.
Link: Wikipedia article: ISO 8601
Last sunday we change the time (-1h) in middle europe. I was making some tests but something does not let me sleep with the java time parser. This is the code
public static void main(String[] args) {
String dateFormatPattern = "yyyy-MM-dd HH:mm:ss";
String dateUtc = "2016-10-09 12:50:00";
SimpleDateFormat dateFormatUtc = new SimpleDateFormat(dateFormatPattern);
dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
SimpleDateFormat dateFormatLisboa = new SimpleDateFormat(dateFormatPattern);
dateFormatLisboa.setTimeZone(TimeZone.getTimeZone("Europe/Lisboa"));
SimpleDateFormat dateFormatMadrid = new SimpleDateFormat(dateFormatPattern);
dateFormatMadrid.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
SimpleDateFormat dateFormatParis = new SimpleDateFormat(dateFormatPattern);
dateFormatParis.setTimeZone(TimeZone.getTimeZone("Europe/Paris"));
System.out.println("UTC: "+dateUtc);
try {
Date d = dateFormatUtc.parse(dateUtc);
System.out.println("Lisboa: "+dateFormatLisboa.format(d));
System.out.println("Madrid: "+dateFormatMadrid.format(d));
System.out.println("Paris: "+dateFormatParis.format(d));
} catch (ParseException e) {
e.printStackTrace();
}
}
And this is the output
UTC: 2016-10-09 12:50:00
Lisboa: 2016-10-09 12:50:00
Madrid: 2016-10-09 14:50:00
Paris: 2016-10-09 14:50:00
Why the difference between UTC and Madrid time are 2 hours? Now in madrid is UTC+1.
Thanks.
The times are correct as the clocks changed on the 30th October at 2am
if you change you code to this
String dateUtc = "2016-11-09 12:50:00";
You get this output, giving the correct 1 hour difference.
UTC: 2016-11-09 12:50:00
Lisboa: 2016-11-09 12:50:00
Madrid: 2016-11-09 13:50:00
Paris: 2016-11-09 13:50:00
The timezone is due to the when the date object is actually referencing. So it is correct for that time
The accepted Answer by French is correct. The values overlapped the cutover in Daylight Saving Time (DST).
I am just pointing out that your code is using old date-time classes, now legacy, supplanted by the java.time classes.
Parse the input value as a LocalDateTime because it lacks any indicator of time zone or offset-from-UTC.
Replace the SPACE in the middle with a T to comply with ISO 8601 format used by default in the java.time classes for parsing/generating strings.
LocalDateTime ldt = LocalDateTime.parse( "2016-10-09 12:50:00".replace( " " , "T" ) );
We know from the business context that UTC is intended for this input string. So assign an offset of UTC.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
Adjust into a time zone by applying a ZoneId to get a ZonedDateTime.
ZoneId z = ZoneId.of( "Europe/Lisboa" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Hello I'm trying to convert a string in the format "17:50" to a date in android but when I try to run this code I get the correct hour from the string but the full date is from 1970. I need this date to schedule some local notifications on a given time of the day or in the next day.
String dtStart = "17:50";
SimpleDateFormat format = new SimpleDateFormat("H:mm");
try {
Calendar cal = Calendar.getInstance();
Date date = format.parse(dtStart);
cal.setTime(date);
System.out.println(cal.getTime());
} catch (ParseException e) {
e.printStackTrace();
}
Thu Jan 01 17:50:00 BRT 1970
It's not an error, your code works well. Just if you want to get current date, you have to add the difference between current day and 1st of January 1970.
Your parsed date gives you 17:30 hours, which means 17 * 60 * 60 * 1000 ms + 30 * 60 + 1000 ms.
This way you can find current day: https://stackoverflow.com/a/1908419/4142087
What Anton suggested was correct, and the current day / next day logic is your custom implementation. You have to check current time and if it past that time, jump to setting up the alarm the next day.
java.time
You need a time-of-day class to represent your intended meaning. The legacy date-time classes from the earliest versions of Java lack such a class. The java.sql.Time class pretends to do this, but actually contains a date as well due to poor design decisions.
LocalTime
You want the LocalTime class for a time-of-day value without a date and without a time zone.
It uses a generic 24-hour single-day clock. Adding/subtracting spans of time wraps around the clock since it lacks any concept of dates.
Define a formatting pattern to match your input string.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "H:mm" ) ; // Uppercase `H` means 24-hour clock, lowercase `h` means 12-hour clock.
Parse input string.
String input = "7:50" ;
LocalTime lt = LocalTime.parse( input , f ) ;
Generate a string in standard ISO 8601 format.
String output = lt.toString() ;
07:50
Perhaps your business logic requires assigning the time-of-day to a date. To determine a moment, a point on the timeline, you must also specify a time zone.
LocalDate ld = LocalDate.of( 2018 , Month.MARCH , 27 ) ;
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I have a POST end-point that takes a couple of values, one being endDate and startDate. When the JSON posts in as:
{ "startDate" : "2015-01-30", "endDate" : "2015-12-30" }
Spring converts it to a java.util.Date Object that is always one day behind. In the logs I see:
Validating that startDate Thu Jan 29 16:00:00 PST 2015 < endDate Tue Dec 29 16:00:00 PST 2015
So it got the timezone correct. I had assumed it was related to UTC conversions, but I'm not sure how to configure this or modify it so that it converts it using the proper off-set. The timestamp portion of it isn't required - I only care that the year, day, and month match what is passed in.
if it matters, I'm using Spring (happened with 4.0.6 and 4.1.7) and a POST
tl;dr
LocalDate.parse( "2015-01-30" )
Use the right data type for the job
You are trying to fit a date-only value into a date-time type, java.util.Date. Square peg, round hole. While trying to come up with a time-of-day to associate with your date, a time zone is being injected, hence your problem.
LocalDate
Solution:
Never use the terrible old legacy date-time classes such as java.util.Date. Use only the modern java.time classes.
For a date-only value, use LocalDate.
Your input string happens to be in standard ISO 8601 format. The java.time classes use ISO 8601 formats by default when parsing/generating strings. So no need to specify a formatting pattern.
LocalDate ld = LocalDate.parse( "2015-01-30" ) ;
ZonedDateTime
If you want a moment, a date with a time-of-day, let java.time determine the first moment of the day. Never assume that moment is 00:00:00. In some zones on some dates it may be another time such as 01:00:00 because of anomalies such as Daylight Saving Time (DST).
ZonedId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ; // Let java.time determine the first moment of that date in that zone.
Instant
To adjust from to UTC (same moment, different wall-clock time), extract an Instant.
Instant instant = zdt.toInstant() ; // Adjust to UTC. Same moment, same simultaneous point on the timeline, different wall-clock time.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
String str="2015-01-30";
try{
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd");
isoFormat.setTimeZone(TimeZone.getTimeZone("PST"));
Date date = isoFormat.parse(str);
System.out.println(date);
}catch(ParseException e){
e.printStackTrace();
}
Check here http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-webdatabinder how to customize automatic Spring conversion:
#Controller
public class MyFormController {
#InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
// ...
}
Im having a problem with java date's, when i pass a date before 1949 into the bellow method.
The date i have returned is for example 2049, im aware it has somthing to do with the date format and thought using yyyy instead of RRRR would have fixed it. But i just dont understand why or how to reslove it. Any help will be much apreciated
public static java.sql.Date parseDate(String date) throws ParseException {
if (date != null) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
return new java.sql.Date(dateFormat.parse(date).getTime());
}
return null;
}
Thanks Jon
let me format that for you..
public static java.sql.Date parseDate(String date) throws ParseException {
if (date != null) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
return new java.sql.Date(dateFormat.parse(date).getTime());
}
return null;
}
This I suspect is what you want...
private Date convertDate() throws ParseException
{
String dateStr = "21-02-2010";
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
Date date = null;
if (dateStr != null)
{
date = new Date(dateFormat.parse(dateStr).getTime());
}
System.out.println(date);
return date;
}
For 21-02-2010 you will get...
Sun Feb 21 00:00:00 GMT 2010
For 21-02-1938 you will get...
Mon Feb 21 00:00:00 GMT 1938
Does that help? I might of been due to you having MMM in your code.
tl;dr
java.sql.Date.valueOf(
LocalDate.parse( "12-Jan-23" , DateTimeFormatter.ofPattern( "dd-MMM-uuuu" , Locale.US ) )
)
Time Zone
Your code ignores the crucial issue of time zone. Determining a date requires a time zone. For any given moment, the date varies around the globe by zone.
Your code uses Date which is always in UTC. So your date value produced from the misnamed Date class will be accurate for UTC but not valid for other time zones such as America/Montreal or Asia/Kolkata.
Using java.time
The modern way to do this work is with the java.time classes that supplant the troublesome old legacy date-time classes.
The LocalDate class represents a date-only value without time-of-day and without time zone.
To parse an incoming string, define a formatting pattern with DateTimeFormatter. Specify a Locale for the human language to be used in translating the name of the month.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-uuuu" , Locale.US );
LocalDate localDate = LocalDate.parse( "12-Jan-2017" , f );
With JDBC 4.2 and later, you can pass the LocalDate directly to your database with setObject and getObject methods.
For a JDBC driver not yet updated, fall back to the java.sql types.
java.sql.Date sqlDate = java.sql.Date.valueOf( localDate );
LocalDate localDate = sqlDate.toLocalDate();
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.