Saving a timestamp value from a given string value - java

I am having a string value in format "Tue Apr 30 00:00:00 UTC 1996";
. I want this value to be converted into a timestamp field in "30-APR-96 05:30:00.000000000 AM"
What i tried here is
DateFormat formatter = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");
Date date = formatter.parse(str);
Timestamp ts = new Timestamp(date getTime());
SimpleDateFormat fo = new SimpleDateFormat("dd-MMM-yy hh:mm:ss.SSSSSSSSS a");
fo.format(ts);
//When i try here Timestamp.valueOf(fo.format(ts));
I am getting an exception Timestamp format must be yyyy-mm-dd hh:mm:ss[.ffffff]
In DB when i see i have the type as Timestamp and values are stored in "30-APR-96 05:30:00.000000000 AM"

tl;dr
myPreparedStatement.setObject(
… ,
ZonedDateTime
.parse(
"Tue Apr 30 00:00:00 UTC 1996" ,
DateTimeFormatter
.ofPattern( "E MMM dd HH:mm:ss zzz uuuu" )
.withLocale( Locale.US )
)
.toOffsetDateTime()
);
Avoid legacy date-time classes.
You are using terribly flawed date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310. Never use Date, Calendar, SimpleDateFormat, etc.
In particular, your input data uses a resolution of nanoseconds, while thé java.util.Date class is limited to milliseconds.
ISO 8601
Let me mention that data exchange should be using standard ISO 8601 formats for date-time values transmitted as text. The standard formats are concise, unambiguous, and easily read by both humans and machines.
Use custom or localized formats only for presentation to user, not for storage and data exchange.
So, "Tue Apr 30 00:00:00 UTC 1996" would be 1996-04-30T00:00:00Z where Z is short for +00:00, an offset from UTC of zero hours-minutes-seconds.
java.time
The java.time classes do support the nanoseconds resolution needed for your data inputs.
Define a formatting pattern to match the input. Specify a Locale to determine the human language and cultural norms used in translation.
Locale locale = new Locale( "en" , "IN" ) ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM dd HH:mm:ss zzz uuuu" ) ;
Parse your input.
ZonedDateTime zdt = ZonedDateTime.parse( "Tue Apr 30 00:00:00 UTC 1996" , f ) ;
See this code run live at IdeOne.com.
zdt.toString(): 1996-04-30T00:00Z[UTC]
Apparently you want to see this moment as it appears in the India 🇮🇳 time zone. Specify the desired time zone as a ZoneId object.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
Apply the zone to get another ZonedDateTime object.
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant( z ) ;
See this code run live at IdeOne.com.
zdtKolkata.toString(): 1996-04-30T05:30+05:30[Asia/Kolkata]
You asked for a java.sql.Timestamp object. That class is one of the terrible legacy classes to avoid. And it is unnecessary. JDBC 4.2 and later requires that a JDBC driver support java.time.
To write a moment to a database, we need to use OffsetDateTime rather than ZonedDateTime. The SQL standard does not specify time zones, only offsets.
And, there is no need for the India-specific value. Most databases saving into a column of a type akin to the SQL standard type TIMESTAMP WITH TIME ZONE will automatically adjust inputs into UTC (an offset of zero).
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;
Retrieval.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Beware: Verify the data type of your database column. If you are using a column of a type akin to the SQL standard type TIMESTAMP WITHOUT TIME ZONE, you are using the wrong type. That type cannot represent a moment, a specific point on the timeline. Such a type has only a date with time of day, but lacks the context of an offset.

Related

Java Converting Retrieved TimeStamp to Instant Gives Wrong Day

I've made a simple method which is used to convert a timestamp retrieved from a database into a LocalDate. However for some reason I keep getting the wrong day in the conversion. I've shared the code below.
private LocalDate getLocalDateFromTimeStamp(Row row, String key){
return LocalDate.parse(row.getTimestamp(key).toInstant().atZone(ZoneOffset.UTC).toLocalDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}
So the date I'm expecting is 2022-12-21 but what I get is 2022-12-22.
When I debug and check what
row.getTimestamp(key)
gets me a Date object of Wed Dec 21 20:47:46 CST 2022 which is what I expect.
When I check what
row.getTimestamp(key).toInstant()
does, I get "2022-12-22T02:47:46.299Z". And I think this is where the problem is popping up and I'm not sure why it's happening. The LocalDate that's returned by the method is "2022-12-22".
If anyone could shine a light on this I'd really appreciate it as I'm lost as to why this is happening.
Try it like this. Check out DateTimeFormatter for details on the following arguments.
String date = "Wed Dec 21 20:47:46 CST 2022";
EEE three letter day of week
MMM three letter month
dd integer day
HH:mm:ss time using 24 hour clock
z time zone name (CST)
yyyy year
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy");
LocalDate dt = LocalDateTime.parse(date, dtf).toLocalDate();
System.out.println(dt);
prints
2022-12-21
Updated
If you actually have an instance of Date you might try the following:
LocalDate ldt = LocalDate.ofInstant(date.toInstant(),
ZoneId.systemDefault());
tl;dr
Avoid unnecessary string manipulation. Use date-time types for date-time values.
myResultSet
.getObject( … , OffsetDateTime.class ) // For any database column of a data type akin to the SQL standard type of `TIMESTAMP WITH TIME ZONE`.
.toLocalDate() // Extract the date portion from the returned `OffsetDateTime` object.
.toString() // Generate text in standard ISO 8601 format.
Details
The Timestamp class is part of the terrible date-time classes that are now legacy. Use only their replacements, the modern java.time classes defined in JSR 310.
Instead of Timestamp, use OffsetDateTime with JDBC 4.2 and later. Do this for any database column of a data type akin to the SQL standard type of TIMESTAMP WITH TIME ZONE.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Your Question is not clear, but you seem to want the date portion of that moment as seen with an offset from UTC of zero hours-minutes-seconds.
The retrieved OffsetDateTime is likely already in UTC. But let’s be sure:
OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;
Extract the date portion.
LocalDate localDate = odtUtc.toLocalDate() ;
To generate text in standard ISO 8601 format, call toString.
String output = localDate.toString() ;

Convert from String to either LocalDateTime or ZonedDateTime

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);

Converting string to date 2021-12-10T00:00:00 in java

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.

Format LocalDateTime using FormatStyle.MEDIUM plus time zone

I have a LocalDateTime object that I format as follows:
LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
System.out.println(localDateTime.format(formatter));
That prints a nicely readable date of Oct 20, 2021 1:00:02 PM.
But I would like to also add the time zone. My understanding is I need to use ZonedDateTime:
ZonedDateTime zdt = localDateTime.atZone(ZoneId.of("America/New_York"));
System.out.println(zdt);
But that produces the not so readable 2021-10-20T13:00:02.921-04:00[America/New_York].
Is there some way to format a ZonedDateTime so it's concise and readable like that produced by FormatStyle.MEDIUM, but also appended by the timezone (e.g: Oct 20, 2021 1:00:02 PM EST)?
Note: I gather from this answer that I should not actually use "pseudo-zones", such as EST, due to their non-standardized nature.
tl;dr
If you want a hint as to the time zone in use, use the LONG format for time-of-day portion. Optionally specify a different format such as MEDIUM for the date portion.
ZonedDateTime
.now( ZoneId.of( "America/New_York" ) )
.format(
DateTimeFormatter
.ofLocalizedDateTime(
FormatStyle.MEDIUM , // Date portion style.
FormatStyle.LONG // Time-of-day portion style.
)
.withLocale( Locale.US ) // Locale determines the human language and cultural norms used in localizing.
)
See this code run live at IdeOne.com.
Oct 20, 2021, 4:48:46 PM EDT
Never use EDT, CST, IST, and such for data-exchange. Do not attempt parsing of such values. These are not real time zones, are not standardized, and are not even unique!
Avoid LocalDateTime.now
I cannot imagine any scenario where calling LocalDateTime.now is the right thing to do. You capture the date and time-of-day but lack the context of a time zone or offset-from-UTC. So a LocalDateTime by definition cannot represent a moment, is not a point on the timeline.
If you want to capture the current moment without committing to a particular time zone, capture the current moment as seen with an offset-from-UTC of zero hours-minutes-seconds.
Instant instant = Instant.now() ; // Current moment as seen in UTC.
Use ZonedDateTime.now
If you want to capture the current moment as seen in America/New_York time zone, start with a ZonedDateTime.
ZonedDateTime.now( ZoneId.of( "America/New_York" ) )
To generate text representing a java.time object, use toString method to get text in standard ISO 8601 format. While such output may seem less readable at first glance, the standard formats are designed to be maximally readable by people across cultures.
To get a localized format, I suggest you let java.time automatically localize.
ZoneId z = ZoneId.of( "America/New_York" );
ZonedDateTime zdt = ZonedDateTime.now( z );
System.out.println( "zdt represented in standard ISO 8601 format: " + zdt.toString() );
Locale locale = Locale.US ;
DateTimeFormatter f_US = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( locale ) ;
String outputLocalized_US = zdt.format( f_US ) ;
String outputLocalized_CA_fr = zdt.format( f_US.withLocale( Locale.CANADA_FRENCH ) ) ;
System.out.println( outputLocalized_US ) ;
System.out.println( outputLocalized_CA_fr ) ;
When run.
zdt represented in standard ISO 8601 format: 2021-10-20T16:37:57.752554-04:00[America/New_York]
Oct 20, 2021, 4:37:57 PM
20 oct. 2021 16 h 37 min 57 s
Separate formats for date & time
You can specify different formats for the date versus time-of-day portions. Use a longer format for time-of-day portion to get a hint of the time zone while using a shorter format for date portion, if you so desire.
DateTimeFormatter
.ofLocalizedDateTime(
FormatStyle.MEDIUM , // Date portion format.
FormatStyle.LONG // Time-of-day portion format.
)
Is there some way to format a ZonedDateTime so it reads similar to
that produced by FormatStyle.MEDIUM, but is appended by the
timezone - say, something like: Oct 20, 2021 4:05:13 PM EST?
You can use the format, MMM d, uuuu h:mm:ss a zzz with the DateTimeFormatter.
Demo:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/New_York"));
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MMM d, uuuu h:mm:ss a zzz", Locale.ENGLISH);
System.out.println(now.format(dtf));
}
}
Output:
Oct 20, 2021 6:41:45 PM EDT
ONLINE DEMO
the ZonedDateTime can retrieve the current ZoneId. With the Zone, you can just use the getDisplayName(TextStyle style, Locale locale) getter. Just experiment which TextStyle is the best for you.
zdt.getZone().getDisplayName(TextStyle.SHORT, Locale.ENGLISH)
==> ET
Note that if you use LONG or FULL for the time style, the zone will be included:
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/New_York"));
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.LONG);
System.out.println(zdt.format(formatter));
In the US locale, this prints:
Oct 20, 2021, 4:34:16 PM EDT
This is documented here:
The FULL and LONG styles typically require a time-zone. When formatting using these styles, a ZoneId must be available, either by using ZonedDateTime or withZone(java.time.ZoneId).
In this case, a time style of LONG happens to be the same as MEDIUM, but if you have to use MEDIUM for some reason, you can use a DateTimeFormatterBuilder and add the zone by hand:
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/New_York"));
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))
.appendLiteral(" ")
.appendZoneText(TextStyle.SHORT).toFormatter();
System.out.println(zdt.format(formatter));
The advantage of this is that you can choose what style of timezone name you want. On the other hand, you might run into localisation issues, because I'm not sure if it is natural in all locales to put the timezone last.

convert java.util.Date to java.util.Date with different formating in JAVA [duplicate]

This question already has answers here:
want current date and time in "dd/MM/yyyy HH:mm:ss.SS" format
(11 answers)
display Java.util.Date in a specific format
(11 answers)
Closed 2 years ago.
I get Date as java.util.Date(not String) : (java.util.Date) Mon Jul 13 00:00:00 IST 2020
I want to convert it to : 2020-07-13T00:00 format==>("yyyy-MM-dd'T'HH:mm") but as DATE not String.
I tried following code:
Date scheduleDate=details.getScheduledDate(); // This value is fetched from object passed-- [scheduleDate = (java.util.Date) Mon Jul 13 00:00:00 IST 2020]
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
sd.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
String dateFormat=sd.format(scheduleDate); //Here I get [dateFormat = (java.lang.String) "2020-07-13T00:00"]
Date date = sd.parse(dateFormat); //[date = (java.util.Date) Mon Jul 13 00:00:00 IST 2020]
I observed that string format has correct(as expected ) value but the value changes back when I convert it to java.util.date.
Does java.util.Date support yyyy-MM-dd'T'HH:mm format ?
If yes, Can anyone suggest me with any good approach/direction/topics/library to look into.
Thank You..
tl;dr
Convert from legacy class to modern class. Adjust from UTC to a time zone. Generate text in standard ISO 8601. We omit the context of time zone or offset in our output because you so requested, against my recommendation.
myJavaUtilDate
.toInstant()
.atZone( ZoneId.of( "Asia/Kolkata" ) )
.truncatedTo( ChronoUnit.MINUTES )
.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME )
I expect using UTC and including the offset would be wiser.
myJavaUtilDate
.toInstant()
.toString()
Details
Date-time objects do not have a format, only text has a format.
Use java.time classes, never java.util.Date.
Convert your legacy Date object to its modern replacement, java.time.Instant.
Instant instant = myJUDate.toInstant() ;
Adjust from UTC to your desired time zone.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Apparently you do not care about the the second of minute. So let’s truncate that to zero seconds.
ZonedDateTime zdt = zdt.truncatedTo( ChronoUnit.MINUTES ) ;
Generate text in your desired format. Java comes bundled with a formatter already defined for your format.
String output = zdt.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) ;
I showed that format because asked. But I do not recommend it. That format fails to indicate a time zone or offset-from-UTC. So if it says noon, the reader does not know if that means noon in Tokyo Japan 🇯🇵, noon in Toulouse France 🇫🇷, or noon in Toledo Ohio Us 🇺🇸 — three very different moments, several hours apart.
When communicating a moment, a specific point on the timeline, textually it is usually best to do so in UTC. And use ISO 8601 standard formats. Commonly a Z is placed on the end to indicate UTC, an offset of zero hours-minutes-seconds.
Instant instant = zdt.toInstant() ;
String output = instant.toString() ;

Categories

Resources