This may be an extremely simple typo that I have in my code, but I just can't make it work no matter what I do.
I have the following code:
String date="2014-05-22";
String time="09:09:04.145"
String dateAndTime=date.concat(" "+ time);
DateFormat convertDate=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSSZ");
Date dateOfMeasurement=convertDate.parse(dateAndTime);
I have tried using yyyy-MM-dd'T'HH:mm:ss:SSSZ and yyyy-MM-dd HH:mm:ss:SSS for the formatting, but nothing works.
What am I doing wrong?
Thank you very much.
java.time
You are using troublesome old legacy date-time classes now supplanted by the java.time classes.
ISO 8601
Your inputs happen to comply with ISO 8601 standard. The java.time classes use ISO 8601 formats by default when parsing/generating Strings that represent date-time values. So no need to specify a formatting pattern.
LocalDate ld = LocalDate.parse( "2014-05-22" );
LocalTime lt = LocalTime.parse( "09:09:04.145" );
LocalDateTime ldt = LocalDateTime.of( ld , lt );
Time zones
A LocalDateTime has no concept of time zone or offset-from-UTC. So it does not represent a moment on the timeline.
For an actual moment, assign a time zone. Perhaps you intended the inputs to represent a moment in UTC.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
Or perhaps you know from the context that another particular time zone was intended.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( z );
Strings
The format you were attempting to assemble is also defined by the ISO 8601 standard. Simply call toString to generate such a value.
An Instant is a basic building-block class in java.time, representing a moment on the timeline in UTC with a resolution up to nanoseconds.
String output = zdt.toInstant().toString(); // 2016-09-08T02:46:15Z
The ZonedDateTime extends standard format by wisely appending the name of the time zone in square brackets.
String output = zdt.toString(); // 2016-09-07T23:46:15-03:00[America/Montreal]
DateFormat convertDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date dateOfMeasurement=convertDate.parse(dateAndTime);
Related
I am trying to implement java.time to parse different date formats and return as java.sql.Date. However I am loosing time if I use java.sql.Date.valueOf(LocalDate date).
How I can achive the same way as java.sql.Date(java.util.Date date.getTime())?
Possible formats in my application are.
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ssZ");
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter datetimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
DateTimeFormatter datetimeFormatterMil = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
import java.sql.Date;
public Date oslcStringToDate(String str) throws ParseException
{
//remove colon in time zone
Date date = null;
if (!str.equalsIgnoreCase(NULL)) {
int colonPos = str.length() - 3;
str = str != null && str.length() > 3 && str.charAt(colonPos) == ':' ?
str.substring(0, colonPos) + str.substring(colonPos + 1)
: str.endsWith("Z") ?
str.substring(0, str.length() - 1) + "+0000"
: str;
date = str.indexOf("T") > 0 ?
str.indexOf(".") > 0 ?
java.sql.Date.valueOf(LocalDateTime.parse(str, datetimeFormatterMil).toLocalDate())
: java.sql.Date.valueOf(LocalDateTime.parse(str, datetimeFormatter).toLocalDate())
: java.sql.Date.valueOf(LocalDateTime.parse(str, dateFormatter).toLocalDate());
}
return date;
}
Do not mix legacy and modern classes
if I use java.sql.Date.valueOf(LocalDate date)
Never mix the terrible legacy classes with their replacement, the modern java.time classes defined in JSR 310.
When handed an object of a legacy class, immediately convert. You can convert to and fro by way of to…/from…/valueOf methods found on the old classes.
LocalDate ld = myJavaSqlDate.toLocalDate() ;
And the other direction.
java.sql.Date d = Date.valueOf( myLocalDate ) ;
Avoid legacy classes
With JDBC 4.2 and later, support for the java.time classes is required in your JDBC driver.
So use only the java.time classes. No need to ever use either Date, nor Calendar, SimpleDateFormat, Timestamp, etc.
Date-only values
The LocalDate class represents a date-only, without a time-of-day, without a time zone or offset-from-UTC. So a LocalDate is a year, month, and day — nothing more.
The java.sql.Date class pretends to represent a date-only value. But due to a tragically poor design decision, the class inherits from java.util.Date which does have a time-of-day. And even more confusing, the java.util.Date class is supposed to represent a moment as seen in UTC, but nevertheless contains a time zone used when generating text. These legacy classes are a master class in how to not do OOP.
You said:
However I am loosing time if I use java.sql.Date.valueOf(LocalDate date).
If you mean the resulting java.sql.Date has no time-of-day, yes, of course, that is a feature, not a bug. As mentioned above, objects of this class actually do have a time-of-day because of inheritance, but the class pretends to have a date-only (year-month-day).
You said:
How I can achive the same way as java.sql.Date(java.util.Date date.getTime())?
I cannot understand your goal here. So, after again advising against ever using these awful legacy classes, I will layout some of the possible types for use with SQL.
standard SQL
java.time ☑️
legacy ❌
DATE
LocalDate
java.sql.Date
TIME
LocalTime
java.sql.Time
TIMESTAMP WITHOUT TIME ZONE
LocalDateTIME
no support
TIMESTAMP WITH TIME ZONE
OffsetDateTime
java.sql.Timestamp
ISO 8601
Your Question is not clear, but apparently you are trying to parse text in the format of "yyyy-MM-dd'T'HH:mm:ss.SSSZ".
This format happens to comply with the ISO 8601 standard. The java.time classes use the standard formats by default when parsing/generating text. So no need to specify a formatting pattern.
Instant instant = Instant.parse( "2022-01-23T12:34:56.789Z" ) ;
To generate such text:
String output = instant.toString() ;
To record to a database, convert to the class mapped in JDBC to the standard SQL type of TIMESTAMP WITH TIME ZONE.
That SQL name is a misnomer, as the SQL standard was written with mere offset-from-UTC in mind, not real time zones. An offset is merely a number of hours-minutes-seconds ahead or behind the temporal prime meridian of UTC. A time zone, in contrast, is a named history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
Retrieval.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Note that LocalDateTime is exactly the wrong class to be using in this context. The LocalDateTime class purposely lacks the context of an offset or zone. With only a date and a time-of-day, a LocalDateTime object is inherently ambiguous with regard to the timeline.
If you want to store only the date portion of your ISO 8601 string, you will need to think about time zones. For any given moment, the date varies around the globe by time zone. A moment can be “tomorrow” in Tokyo Japan while simultaneously “yesterday” in Toledo Ohio US.
Call toLocalDate to extract the date portion of an OffsetDateTime or ZonedDateTime object.
LocalDate dateInTokyo = instant.atZone( ZoneId.of( "Asia/Tokyo" ) ).toLocalDate() ;
LocalDate dateInUtc = instant.atOffset ZoneOffset.UTC ).toLocalDate() ;
LocalDate dateInToledo = instant.atZone( ZoneId.of( "America/New_York" ) ).toLocalDate() ; // Time zone name for Toledo Ohio US is `America/New_York`.
Write to a database column of a type akin to the SQL standard type DATE.
myPreparedStatement.setObject( … , dateInTokyo ) ;
Retrieval.
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
All of these issues have been covered many many times already in Stack Overflow. Search to learn more.
Hi I want to convert String value 2020-12-16T19:20:30+01:00 UTC to either LocalDateTime or ZonedDateTime in java
I tried solution:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-DDThh:mm:ssTZD", Locale.ENGLISH);
final String responseTimeStamp = "2020-12-16T19:20:30+01:00 UTC";
ZonedDateTime zdt = ZonedDateTime.parse(responseTimeStamp, dtf);
Which gives me the error
Exception in thread "main" java.lang.IllegalArgumentException: Unknown pattern letter: T at java.base/java.time.format.DateTimeFormatterBuilder.parsePattern(DateTimeFormatterBuilder.java:1815) at java.base/java.time.format.DateTimeFormatterBuilder.appendPattern(DateTimeFormatterBuilder.java:1712) at java.base/java.time.format.DateTimeFormatter.ofPattern(DateTimeFormatter.java:588) at learning/learning.SpringDemo.main(SpringDemo.java:21)
tl;dr
OffsetDateTime
.parse(
"2020-12-16T19:20:30+01:00 UTC"
.replace( " UTC" , "" )
)
.withZoneSameInstant(
ZoneId.of( "America/Edmonton" )
)
ISO 8601
Your input string:
2020-12-16T19:20:30+01:00 UTC
… nearly complies with the ISO 8601 standard for data-exchange date-time formats. To fully comply, delete the SPACE and UTC from the end. The +01:00 at the end means “one hour ahead of UTC", so the UTC at the end is redundant.
String input = "2020-12-16T19:20:30+01:00 UTC".replace( " UTC" , "" ) ;
Offset versus time zone
Parse as an OffsetDateTime because your input indicates small offset from UTC, not a time zone.
An offset is merely a number of hours-minutes-seconds ahead/behind the prime meridian of UTC. A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians. A time zone has a name in format of Continent/Region, such as Europe/Paris and Africa/Tunis.
OffsetDateTime
So the other Answer’s suggestion to use ZonedDateTime for parsing is misguided as no time zone is indicated. Your input has only an offset, therefore use OffsetDateTime.
No need to specify a formatting pattern. Our modified input complies with ISO 8601, and the java.time classes use those standard formats by default when parsing/generating strings.
OffsetDateTime odt = OffsetDateTime.parse( input ) ;
LocalDateTime
You asked how to get a LocalDateTime. That class lacks any concept of offset or time zone. So beware, if you convert from OffsetDateTime, you are discarding valuable information.
So while I don’t recommend doing this, here is the code.
LocalDateTime ldt = odt.toLocalDateTime() ;
ZonedDateTime
You asked how to adjust into a time zone.
To adjust from our offset to a time zone, merely specify the desired time zone.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = odt.withZoneSameInstant( z ) ;
There are a few things wrong with your code. I suggest you to take a look at the DateTimeFormatter documentation.
YYYY -> This means week-based-year, you can have a look here to see the difference between year-of-era. So you should be using yyyy.
DD -> This means day-of-year, so December 16 is equal to 350. In your case you want to use dd, day-of-month.
T -> There isn't a pattern for T, so you can put it like a text to formmat you date 'T'
TZD -> I don't know what you are trying to use here and I couldn't find the patter +03:00 UTC, you can try to use O
So your final pattern should be "yyyy-MM-dd'T'HH:mm:ssO". It doens't work for UTC and I couldn't find it on ZoneId list, maybe because UTC is +00:00 already, so UTC+01:00 is equal to +01:00.
After a lot of working understanding the pattern, I found out that you are looking for ISO_ZONED_DATE_TIME, so you could just change your code like below:
DateTimeFormatter dtf = DateTimeFormatter.ISO_ZONED_DATE_TIME;
final String responseTimeStamp = "2020-12-16T19:20:30+01:00";
ZonedDateTime zdt = ZonedDateTime.parse(responseTimeStamp, dtf);
I'm tring to convert this date string "2021-12-10T00:00:00" into a Date but when i deserialize it i got this.
Thu Dec 09 19:00:00 COT 2021.
it seems I'm losing one day.
Can anyone help me?
"startDate": "2021-12-10T00:00:00", and the result is this
2021-12-09T19:00:00.000-0500
tl;dr
java.util.Date.from(
LocalDateTime
.parse( "2021-12-10T00:00:00" )
.atZone(
ZoneId.of( "America/Bogota" )
)
.toInstant()
)
Details
I am guessing that you are using the terrible legacy date-time classes such as Date and Calendar. Don’t. Use only java.time class.
Your input string complies with the ISO 8601 standard for date-time formats. The java.time classes use these standard formats by default when parsing/generating strings. So no need to specify a formatting pattern.
LocalDateTime ldt = LocalDateTime.parse( "2021-12-10T00:00:00" ) ;
You said:
I'm tring to convert this date string "2021-12-10T00:00:00" into a Date
That does not make sense.
I assume by “Date”, you meant a java.until.Date. That legacy class represents a moment, a point on the timeline as seen in UTC, that is, with an offset from UTC of zero hours-minutes-seconds.
But your input lacks an indicator of time zone or offset. For example, if that string was meant to represent a moment as seen in UTC, it should have had a Z appended.
I am guessing that you assume the input was meant to represent a moment as seen in Colombia.
ZoneId z = ZoneId.of( "America/Bogota" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
Now we have determined a moment as seen through the wall-clock time used by the people of Colombia.
Generally best to avoid java.util.Date class. But if you must, to interoperate with legacy code not yet updated to java.time, you can convert.
java.util.Date d = Date.from( zdt.toInstant() ) ;
Your start date is 2021-12-10 00:00:00 GMT+0 and your result is 2021-12-09 19:00:00 GMT-5. These times are the same. You can pass a Locale to your SimpleDataFormat constructor to be able to configure the used time zone.
Timestamp timestamp = Timestamp.valueOf("1970-01-01 01:00:00");
System.out.println(timestamp.getTime());
Any idea this code returns -25200000 ?
I thought time after 1970-01-01 00:00:00 will be positive.
You are using a terrible date-time class that was supplanted years ago by the modern java.time classes defined in JSR 310. Never use java.sql.Timestamp.
Parse your input as a LocalDateTime because it lacks an indicator of time zone or offset-from-UTC. Replace the SPACE in middle with a T to comply with ISO 8601 standard for date-time formats.
String input = "1970-01-01 01:00:00".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
Apparently you mean for that to represent a moment in UTC. Apply an offset to get an OffsetDateTime.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;
Get a count of milliseconds since the epoch reference of first moment of 1970 in UTC.
long millis = odt.toInstant().toEpochMilli() ;
3600000
I'm trying to convert current time in MST using below code
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
TimeZone toTimeZone = TimeZone.getTimeZone("MST");
sdf.setTimeZone(toTimeZone);
Date date = new Date();
String strDate = sdf.format(date.getTime());
strDate displaying correct MST time, but after parsing it is giving wrong date time.
Date currentDate = sdf.parse(strDate);
I want current MST time in Date format not in string.
A java.util.Date object does not have a concept of time zone.
There is no way to set a timezone for a Date
There is no way to change the timezone of a Date object
A Date object created with the new Date() default constructor will be initialised with the current time in the system default timezone
All you did is add a time zone information for the formatting part... setTimeZone does not convert anything.
tl;dr
ZonedDateTime zdt = LocalDateTime.parse( input , DateTimeFormatter.forPattern( "dd/MM/uuuu hh:mm:ss" ) ).atZone( ZoneId.of( "America/Denver" ) );
Avoid legacy date-time classes
You are using old outmoded troublesome legacy date-time classes.
java.time
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
Now in maintenance mode, the Joda-Time project also advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.
LocalDateTime
Your input string lacks any indication of offset-from-UTC or time zone. So we must parse as a LocalDateTime. A LocalDateTime has no offset or time zone, so it does not represent a moment on the timeline. Like saying "Christmas starts at midnight on December 25", that only has meaning (only becomes a point on the timeline) when you apply it to a particular time zone somewhere on the planet.
String input = …
DateTimeFormatter f = DateTimeFormatter.forPattern( "dd/MM/uuuu hh:mm:ss" );
LocalDateTime ldt = LocalDateTime.parse( input , f );
ZonedDateTime
If you know the context and can assume the intended offset or time zone, you can create an OffsetDateTime or ZonedDateTime respectively.
Use proper time zone names, named in the format of continent/region. By MST perhaps you meant the America/Denver time zone used in much of the Rocky Mountains parts of the United States, or America/Edmonton used in parts of Canada.
Never use the 3-4 letter abbreviations such as MST. These abbreviations are not true time zones, are not standardized, and are not even unique(!).
ZoneId zoneId = ZoneId.of( "America/Denver" ) ;
ZonedDateTime zdt = ldt.atZone( zoneId ) ;
Converting
I suggest avoiding the notoriously troublesome java.util.Date class. But if you must do so , you may convert to/from java.time types. To interoperate with other code or libraries, convert using new methods added to the old classes. In this case, use a Instant object extracted from the OffsetDateTime or ZonedDatetime and pass to java.util.Date.from.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.
java.util.Date utilDate = java.util.Date.from( zdt.toInstant() ) ;
Going the other direction, use another new method added to the old class, java.util.Instant::toInstant.
Instant instant = utilDate.toInstant();
ZonedDateTime zdt = instant.atZone( zoneId ) ;