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));
}
// ...
}
Related
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.
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 am getting time in string like this "2011-02-27T10:03:33.099-06:00" which is of xml dateTime type. I also have timezone of TimeZone type. How should I convert the dateTime to GregorianCalendar java type in that timezone.
Java has built in code to parse xml datetimes: use DatatypeConverter.parseDateTime(). that will return a Calendar in the parsed TimeZone. you can then set the Calendar TimeZone to your desired target TimeZone for whatever you need to do next.
sdf = new java.text.SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss.S");
parses everything, except the trailing TZ.
sdf.parse (sd);
res168: java.util.Date = Sun Feb 27 10:03:33 CET 2011
From the api docs, I would expect
sdf = new java.text.SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss.SSSz");
to be used to read the -06:00 in the end. But I see, that there is either an offset in the form 0700 expected, or with a prefix of GMT for example "GMT-04:00". So you have to insert that GMT-thingy yourself:
sdf.parse (sd.replaceAll ("(......)$", "GMT$1"))
SDF.parse (str) returns a Date, which has to be converted into a GC:
GregorianCalendar calendar = new GregorianCalendar ();
calendar.setTime (date);
tl;dr
OffsetDateTime.parse( "2011-02-27T10:03:33.099-06:00" )
java.time
The modern approach uses the java.time classes that supplanted the troublesome old legacy date-time classes. Specifically, GregorianCalendar was replaced by ZonedDateTime for a time zone, and OffsetDateTime for a mere offset-from-UTC.
ISO 8601
Your input string happens to comply with the ISO 8601 standard format.
The java.time classes use these standard formats by default when parsing/generating strings. So no need to specify a formatting pattern.
OffsetDateTime
Your input string contains an offset-from-UTC, but not a time zone. So parse as an OffsetDateTime.
OffsetDateTime odt = OffsetDateTime.parse( "2011-02-27T10:03:33.099-06:00" ) ;
ZonedDateTime
If you know for certain the intended time zone, apply a ZoneId to produce a ZonedDateTime.
A time zone is always preferable to a mere offset. A zone is a history of past, present, and future changes to the offset used by the people of a particular region.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Pacific/Galapagos" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
Converting legacy ↔ modern
If you must have a GregorianCalendar object to inter-operate with old code not yet updated to java.time, you can convert. Look to new methods added to the old classes.
GregorianCalendar myGregCal = GregorianCalendar.from( zdt ) ;
And going the other direction…
ZonedDateTime zdt = myGregCal.toZonedDateTime() ;
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.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor 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, 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 am trying to read the system date in CST time zone using Java. I tried the below code but whenever I use formatter.parse() it is returning time in EST time zone.
private Date getTodayInCST() {
Calendar currentdate = Calendar.getInstance();
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
TimeZone obj = TimeZone.getTimeZone("CST");
formatter.setTimeZone(obj);
String today = formatter.format(currentdate.getTime());
try {
return formatter.parse(today);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
tl;dr
ZonedDateTime.now(
ZoneId.of( "America/Chicago" )
)
Details
I am trying to read the system date in CST time zone
By “CST”, do you mean Central Standard Time in North America, or China Standard Time?
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique as seen above with CST.
ZoneId z = ZoneId.of( "America/Chicago" ) ;
java.time
You are using troublesome old date-time classes that are now legacy. Supplanted by the java.time classes.
Get the current moment in UTC. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now() ;
2018-02-26T05:45:24.213610Z
Adjust into another time zone. Same moment, same point on the timeline, different wall-clock time.
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2018-02-25T23:45:24.213610-06:00[America/Chicago]
The above strings are in standard ISO 8601 format. The ZonedDateTime class extends that standard wisely to append the name of the zone in square brackets.
If you want to generate String objects in other formats, use DateTimeFormatter.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu HH:mm:ss" ) ;
String output = zdt.format( f ) ;
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.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor 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, 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.
java.util.Date objects do not contain any timezone information by themselves - you cannot set the timezone on a Date object. The only thing that a Date object contains is a number of milliseconds since the "epoch" - 1 January 1970, 00:00:00 UTC.
If you want to set timezone try it this way
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
format.setTimeZone(TimeZone.getTimeZone("CST"));
System.out.println(format.format(new Date()));
If want to the code to provide the current time considering the daylight saving adjustment from CST to CDT or vice versa ,you can use the
"CST6CDT" timezone. in place of "CST" in SimpleDateFormat.
SimpleDateFormat cstCdtFormat=new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
cstCdtFormat.setTimeZone(TimeZone.getTimeZone("CST6CDT"));
System.out.println(cstCdtFormat.format(new Date()));