Java - Date format for Multiple Scenarios - java

I have a java component to format the date that I retrieve. Here is my code:
Format formatter = new SimpleDateFormat("yyyyMMdd");
String s = "2019-04-23 06:57:00.0";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss.S");
try
{
Date date = simpleDateFormat.parse(s);
System.out.println("Formatter: "+formatter.format(date));
}
catch (ParseException ex)
{
System.out.println("Exception "+ex);
}
The code works great as long as the String s has the format "2019-04-23 06:57:00.0";
My Question is, how to tweak this code so it will work for below scenarios ex,
my s string may have values like
String s = "2019-04-23 06:57:00.0";
or
String s = "2019-04-23 06:57:00";
Or
String s = "2019-04-23";
right now it fails if I don't pass the ms.. Thanks!

Different types
String s = "2019-04-23 06:57:00";
String s = "2019-04-23";
These are two different kinds of information. One is a date with time-of-day, the other is simply a date. So you should be parsing each as different types of objects.
LocalDateTime.parse
To comply with the ISO 8601 standard format used by default in the LocalDateTime class, replace the SPACE in the middle with a T. I suggest you educate the publisher of your data about using only ISO 8601 formats when exchanging date-time values as text.
LocalDateTime ldt1 = LocalDateTime.parse( "2019-04-23 06:57:00".replace( " " , "T" ) ) ;
The fractional second parses by default as well.
LocalDateTime ldt2 = LocalDateTime.parse( "2019-04-23 06:57:00.0".replace( " " , "T" ) ) ;
See this code run live at IdeOne.com.
ldt1.toString(): 2019-04-23T06:57
ldt2.toString(): 2019-04-23T06:57
LocalDate.parse
Your date-only input already complies with ISO 8601.
LocalDate ld = LocalDate.parse( "2019-04-23" ) ;
See this code run live at IdeOne.com.
ld.toString(): 2019-04-23
Date with time-of-day
You can strip out the time-of-day from the date.
LocalDate ld = ldt.toLocalDate() ;
And you can add it back in.
LocalTime lt = LocalTime.parse( "06:57:00" ) ;
LocalDateTime ldt = ld.with( lt ) ;
Moment
However, be aware that a LocalDateTime does not represent a moment, is not a point on the timeline. Lacking the context of a time zone or offset-from-UTC, a LocalDateTime cannot hold a moment, as explained in its class JavaDoc.
For a moment, use the ZonedDateTime, OffsetDateTime, or Instant classes. Teach the publisher of your data to include the offset, preferably in UTC.
Avoid legacy date-time classes
The old classes SimpleDateFormat, Date, and Calendar are terrible, riddled with poor design choices, written by people not skilled in date-time handling. These were supplanted years ago by the modern java.time classes defined in JSR 310.

In case of you have optional parts in pattern you can use [ and ].
For example
public static Instant toInstant(final String timeStr){
final DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH[:mm[:ss[ SSSSSSSS]]]")
.withZone(ZoneId.of("UTC"));
try {
return Instant.from(formatter.parse(timeStr));
}catch (DateTimeException e){
final DateTimeFormatter formatter2 = DateTimeFormatter
.ofPattern("yyyy-MM-dd")
.withZone(ZoneId.of("UTC"));
return LocalDate.parse(timeStr, formatter2).atStartOfDay().atZone(ZoneId.of("UTC")).toInstant();
}
}
cover
yyyy-MM-dd
yyyy-MM-dd HH
yyyy-MM-dd HH:mm
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm:ss SSSSSSSS

Related

convert string date to sql date format

I want to convert this string "2022-01-13 14:33:07.996" to java sql date. I have read the answers and I have converted the string to java util date and then to java sql date. I just don't know how to get the full date in java sql date format
String dateStart = "2022-01-13 14:33:07.996";
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date1 = dateFormat.parse(dateStart);
java.util.Date utilDate = date1;
java.sql.Date sqlDate = new java.sql.Date(date1.getTime());
System.out.println(sqlDate);
in out put i get this
2022-01-13
but I want something like this 2022-01-13 14:33:07.996 in java sql date format
tl;dr
To write date-time values to a database, use appropriate objects, not text. For a date-only value, use LocalDate.
myPreparedStatement
.setObject(
… ,
LocalDateTime
.parse( "2022-01-13 14:33:07.996".replace( " " , "T" ) )
.toLocalDate()
)
Avoid legacy date-time classes
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310.
Date-only
You said:
2022-01-13 14:33:07.996 in java sql date format
That is a contradiction. A java.sql.Date object represents a date-only, not a date with time-of-day.
java.time.LocalDateTime
Parse your input string as a LocalDateTime because it lacks any indicator of time zone or offset. Replace the SPACE in the middle with a T to comply with the ISO 8601 standard.
String input = "2022-01-13 14:33:07.996".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
java.time.LocalDate
Extract the date portion.
LocalDate ld = ldt.toLocalDate() ;
Database access
Write to database.
myPreparedStatement.setObject( … , ld ) ;
Retrieve from database.
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
These matters have been covered many many times already on Stack Overflow. Search to learn more.

Parse non ISO 8601 to ISO_INSTANT

I'm trying parse this String 2020-05-20 14:27:00.943000000 +00:00 and this Wed May 20 14:27:00 CEST 2020 to a ISO_INSTANT, but always return this exception
java.time.format.DateTimeParseException: Text '2020-05-20 14:27:00.943000000 +00:00' could not be parsed at index 10
My code is:
protected Instant parseDateTime(String fechaHora) {
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
TemporalAccessor temporalAccessor = formatter.parse(fechaHora);
LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
Instant result = Instant.from(zonedDateTime);
return result; }
How can I convert this types?
tl;dr
OffsetDateTime.parse(
"2020-05-20 14:27:00.943000000 +00:00" ,
DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss.SSSSSSSSS xxx" )
)
.toInstant()
Fixing your code
Your code is flawed in a few ways.
Use of TemporalAccessor is unnecessary and inappropriate here. To quote its Javadoc:
This interface is a framework-level interface that should not be
widely used in application code. Instead, applications should create
and pass around instances of concrete types
LocalDateTime is not appropriate here as it strips away vital information, the time zone or offset-from-UTC.
You specified a formatter whose formatting pattern does not match your inputs.
Solution
Manipulate your input string to comply with standard ISO 8601 format. Replace the SPACE between date and time with T. Delete SPACE between time and offset.
String input = "2020-05-20 14:27:00.943000000 +00:00" ;
String[] strings = input.split( " " ) ;
String modifiedInput = strings[0] + "T" + strings[1] + strings[2] ;
Parse as an OffsetDateTime, a date with time-of-day in the context of an offset-from-UTC.
OffsetDateTime odt = OffsetDateTime.parse( modifiedInput ) ;
Or, define a formatting pattern to match your input string. Use the DateTimeFormatter class. This has been covered many many times already on Stack Overflow, so search to learn more.
The predefined formatter DateTimeFormatter.ISO_INSTANT that you tried to use does not match your input. Your input does not comply with the ISO 8601 standard used by that formatter.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss.SSSSSSSSS xxx" ) ;
String input = "2020-05-20 14:27:00.943000000 +00:00" ;
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;
See this code run live at IdeOne.com.
odt.toString(): 2020-05-20T14:27:00.943Z
If you need to return an Instant, call toInstant.
Instant instant = odt.toInstant() ;
To see that same moment in the context of a time zone, apply a ZoneId to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
The OffsetDateTime and ZonedDateTime objects represent the same moment, same point on the timeline.
The cause of your exception is the different format between your String 2020-05-20 14:27:00.943000000 +00:00 and ISO_INSTANT ; from DateTimeFormatter ISO_INSTANT accepts strings like 2011-12-03T10:15:30Z and this is not your case. A possible solution to this problem is use a custom DateTimeFormatter like below:
String fechaHora = "2020-05-20 14:27:00.943000000 +00:00";
DateTimeFormatter formatter =DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS ZZZZZ");
TemporalAccessor temporalAccessor = formatter.parse(fechaHora);
LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
Instant result = Instant.from(zonedDateTime);
System.out.println(result); //<-- it will print 2020-05-20T12:27:00.943Z

JAVA 8 Timestamp- Cant we change the format of timestamp in the way we want?

No matter what I do its not working. I want to have it in dd/mm/yyyy I have tried and unable to get it done.Tried with JAVA 8 api of Instant localdate localtime localdatetime too.
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
Date date = dateFormat.parse("23/09/2007");
long time = date.getTime();
Timestamp ts = new Timestamp(time);
System.out.println(ts);
Prints like this 2007-09-23 00:00:00.0;
TimeStamp has its own format, so you need to format it as per your needs
Try,
SimpleDateFormat f = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date date = f.parse("23/12/2007 00:00:00");
String strDate = f.format(date);
System.out.println("Current Date = "+strDate);
java.time
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes.
➥ Never use java.util.Date, java.sql.Date, nor java.sql.Timestamp.
For a date only, without time-of-day and without time zone, use LocalDate.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) ;
String input = "23/09/2007" ;
LocalDate ld = LocalDate.parse( input , f ) ;
Generate text in standard ISO 8601 format.
String output = ld.toString() ;
Generate text in that same custom format.
String output = ld.format( f ) ;

Plus 1 hour and 1 day in date using java 8 apis

I have this code to add 1 hour or 1 day in date Java 8, but doesn´t work
String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
java.text.SimpleDateFormat format = new java.text.SimpleDateFormat(DATE_FORMAT);
Date parse = format.parse("2017-01-01 13:00:00");
LocalDateTime ldt = LocalDateTime.ofInstant(parse.toInstant(), ZoneId.systemDefault());
ldt.plusHours(1);
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date te = Date.from(zdt.toInstant());
What´s wrong? The code shows: Sun Jan 01 13:00:00 BRST 2017
LocalDateTime is immutable and returns a new LocalDateTime when you call methods on it.
So you must call
ldt = ldt.plusHours(1);
Apart from the issue that you don't use the result of your date manipulation (ldt = ldt.plusHours(1)), you don't really need to go via a LocalDateTime for this operation.
I would simply use an OffsetDateTime since you don't care about time zones:
OffsetDateTime odt = parse.toInstant().atOffset(ZoneOffset.UTC);
odt = odt.plusDays(1).plusHours(1);
Date te = Date.from(odt.toInstant());
You could even stick to using Instants:
Instant input = parse.toInstant();
Date te = Date.from(input.plus(1, DAYS).plus(1, HOURS));
(with an import static java.time.temporal.ChronoUnit.*;)
tl;dr
LocalDateTime.parse( // Parse input string that lacks any indication of offset-from-UTC or time zone.
"2017-01-01 13:00:00".replace( " " , "T" ) // Convert to ISO 8601 standard format.
).atZone( // Assign a time zone to render a meaningful ZonedDateTime object, an actual point on the timeline.
ZoneId.systemDefault() // The Question uses default time zone. Beware that default can change at any moment during runtime. Better to specify an expected/desired time zone generally.
).plus(
Duration.ofDays( 1L ).plusHours( 1L ) // Add a span of time.
)
Details
Do not mix the troublesome old legacy classes Date and Calendar with the modern java.time classes. Use only java.time, avoiding the legacy classes.
The java.time classes use the ISO 8601 standard formats by default when parsing and generating strings. Convert your input string by replacing the SPACE in the middle with a T.
String input = "2017-01-01 13:00:00".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
ALocalDateTime does not represent an actual moment, not a point on the timeline. It has no real meaning until you assign a time zone.
ZoneId z = ZoneId.systemDefault() ; // I recommend specifying the desired/expected zone rather than relying on current default.
ZonedDateTime zdt = ldt.atZone( z ) ;
A Duration represents a span of time not attached to the timeline.
Duration d = Duration.ofDays( 1L ).plusHours( 1L ) ;
ZonedDateTime zdtLater = zdt.plus( d ) ;

Date in to UTC format Java

I have a string like this 2013-10-22T01:37:56. I Need to change this string into UTC Date format like this MM/dd/yyyy KK:mm:ss a. I have tried some code but it is not returning the UTC datetime.
My code is
String[] time = itsAlarmDttm.split("T");
String aFormatDate = time[0]+ " "+time[1];
String aRevisedDate = null;
try {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
final Date dateObj = sdf.parse(aFormatDate);
aRevisedDate = new SimpleDateFormat("MM/dd/yyyy KK:mm:ss a").format(dateObj);
System.out.println(aRevisedDate);
} catch (ParseException e) {
itsLogger.error("Error occured in Parsing the Data Time Object: " +e.getMessage());
} catch (Exception e) {
itsLogger.error("Error occured in Data Time Objecct: " +e.getMessage());
}
I am getting the output is MM/dd/yyyy KK:mm:ss a format. But Not UTC time format.
How to solve this issue?
Try this... Worked for me and printed 10/22/2013 01:37:56 AM Ofcourse this is your code only with little modifications.
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC")); // This line converts the given date into UTC time zone
final java.util.Date dateObj = sdf.parse("2013-10-22T01:37:56");
aRevisedDate = new SimpleDateFormat("MM/dd/yyyy KK:mm:ss a").format(dateObj);
System.out.println(aRevisedDate);
Try to format your date with the Z or z timezone flags:
new SimpleDateFormat("MM/dd/yyyy KK:mm:ss a Z").format(dateObj);
SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
// or SimpleDateFormat sdf = new SimpleDateFormat( "MM/dd/yyyy KK:mm:ss a Z" );
sdf.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
System.out.println( sdf.format( new Date() ) );
What Time Zones?
No where in your question do you mention time zone. What time zone is implied that input string? What time zone do you want for your output? And, UTC is a time zone (or lack thereof depending on your mindset) not a string format.
ISO 8601
Your input string is in ISO 8601 format, except that it lacks an offset from UTC.
Joda-Time
Here is some example code in Joda-Time 2.3 to show you how to handle time zones. Joda-Time has built-in default formatters for parsing and generating String representations of date-time values.
String input = "2013-10-22T01:37:56";
DateTime dateTimeUtc = new DateTime( input, DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeUtc.withZone( DateTimeZone.forID( "America/Montreal" );
String output = dateTimeMontréal.toString();
As for generating string representations in other formats, search StackOverflow for "Joda format".
java.time
It’s about time someone provides the modern answer. The modern solution uses java.time, the modern Java date and time API. The classes SimpleDateFormat and Date used in the question and in a couple of the other answers are poorly designed and long outdated, the former in particular notoriously troublesome. TimeZone is poorly designed to. I recommend you avoid those.
ZoneId utc = ZoneId.of("Etc/UTC");
DateTimeFormatter targetFormatter = DateTimeFormatter.ofPattern(
"MM/dd/yyyy hh:mm:ss a zzz", Locale.ENGLISH);
String itsAlarmDttm = "2013-10-22T01:37:56";
ZonedDateTime utcDateTime = LocalDateTime.parse(itsAlarmDttm)
.atZone(ZoneId.systemDefault())
.withZoneSameInstant(utc);
String formatterUtcDateTime = utcDateTime.format(targetFormatter);
System.out.println(formatterUtcDateTime);
When running in my time zone, Europe/Copenhagen, the output is:
10/21/2013 11:37:56 PM UTC
I have assumed that the string you got was in the default time zone of your JVM, a fragile assumption since that default setting can be changed at any time from another part of your program or another programming running in the same JVM. If you can, instead specify time zone explicitly, for example ZoneId.of("Europe/Podgorica") or ZoneId.of("Asia/Kolkata").
I am exploiting the fact that you string is in ISO 8601 format, the format the the modern classes parse as their default, that is, without any explicit formatter.
I am using a ZonedDateTime for the result date-time because it allows us to format it with UTC in the formatted string to eliminate any and all doubt. For other purposes one would typically have wanted an OffsetDateTime or an Instant instead.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601

Categories

Resources