Generating Datetime sequence using Joda-Time API - java

I want to generate a sequence of time in the following format (yyyy-mm-dd hh:mm:ss) with time interval of 15 min. I will give start date and end date.
Used the below code to test the same.
public static void main(String[] args) throws ParseException {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-mm-dd HH:mm:ss");
DateTime dt1 = formatter.parseDateTime("2017-06-21 00:00:00");
DateTime dt2 = formatter.parseDateTime("2017-06-23 00:00:00");
DateTime dateTime1 = new DateTime(dt1);
DateTime dateTime2 = new DateTime(dt2);
List<Date> allDates = new ArrayList();
while( dateTime1.isBefore(dateTime2) ){
allDates.add( dateTime1.toDate() );
dateTime1 = dateTime1.plusMinutes(15);
System.out.println(dateTime1);
}
It generates output like below:
2017-01-21T00:15:00.000+05:30
Expected output is 2017-06-21 00:00:00 , it's not picking up the right date which I wanted.

tl;dr
Use java.time classes, which supplant the Joda-Time project. Convert input to standard format for easy parsing.
LocalDateTime.parse(
"2017-06-23 00:00:00".replace( " " , "T" )
).plus( Duration.ofMinutes( 15 ) )
Details
As noted by JB Nizet, you are using incorrect codes in your formatting pattern. Apparently you are guessing at the codes rather reading the documentation – an unwise practice. These codes have been covered hundreds of times on Stack Overflow, so apparently you are posting here without bothering to first search.
Joda-Time vs java.time
You are using the Joda-Time library. This project is now in maintenance mode, with the team advising migration to the java.time classes.
ISO 8601 standard
Your input strings nearly comply with the ISO 8601 standard. To fully comply, replace the SPACE in the middle with a T. The java.time classes use ISO 8601 formats by default when parsing/generating strings. So no need to define any formatting pattern.
Caveat about LocalDateTime
Your input lacks any indication of time zone or offset-from-UTC. So we will parse as LocalDateTime. Beware that a LocalDateTime is not a real moment, not an actual point on the timeline. Without the context of a time zone or offset, a LocalDateTime is unrealistic.
Solution
LocalDateTime start = LocalDateTime.parse( "2017-06-21 00:00:00".replace( " " , "T" ) ) ;
LocalDateTime stop = LocalDateTime.parse( "2017-06-23 00:00:00".replace( " " , "T" ) ) ;
For defensive programming, verify your start is before your stop. Something like stop.isAfter( start ).
On each loop, add your specified duration of 15 minutes.
Duration d = Duration.ofMinutes( 15 ) ;
LocalDateTime ldt = start ;
List< LocalDateTime > ldts = new ArrayList<>() ;
while( ! ldt.isAfter( stop ) ) { // "Not after" is a shorter way of saying "is earlier than or is equal to".
ldts.add( ldt ) ;
// Set up the next loop.
ldt = ldt.plus( d ) ;
}
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, 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
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.

First of all, read the javadoc. The lowercase mm pattern corresponds to the minutes. To get the months, you need to use uppercase MM. So, your formatter will be like this:
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
And you don't need to do this:
DateTime dateTime1 = new DateTime(dt1);
It's redundant, because you're creating 2 identical objects. Just use the dates returned by parseDateTime method. Or just do:
DateTime dateTime1 = dt1;
And you've already created a DateTimeFormatter, so just use it to format the output as well. Instead of:
System.out.println(dateTime1);
Do this:
System.out.println(formatter.print(dateTime1));
The print method will return the dates in the format you want.
I'm not sure if you wanted to print the first date (2017-06-21 00:00:00). If you want this, just change the order of the plusMinutes and System.out.println lines.
New Java Date/Time API
Joda-Time is in maintainance mode and is being replaced by the new APIs, so I don't recommend start a new project with it. Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".
So, if you can migrate your Joda-Time code, or starting a new project, consider using the new API. If you're using Java 8, you can use the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
The logic is very similar. The only difference is that I used LocalDateTime class, and to convert it to a java.util.Date I need to know in what timezone it is. I used the system's default timezone, which is probably what you want (as your original code also uses the default timezone):
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime1 = LocalDateTime.parse("2017-06-21 00:00:00", formatter);
LocalDateTime dateTime2 = LocalDateTime.parse("2017-06-23 00:00:00", formatter);
List<Date> allDates = new ArrayList();
while (dateTime1.isBefore(dateTime2)) {
// get the date in the system default timezone and convert to java.util.Date
allDates.add(Date.from(dateTime1.atZone(ZoneId.systemDefault()).toInstant()));
dateTime1 = dateTime1.plusMinutes(15);
System.out.println(formatter.format(dateTime1));
}
In Java 8 the Date.from method is available. In ThreeTen Backport (Java 7 and Android), you can use the org.threeten.bp.DateTimeUtils class instead:
allDates.add(DateTimeUtils.toDate(dateTime1.atZone(ZoneId.systemDefault()).toInstant()));

Related

Add n number of days using simpledateformat in java

We have a java code snippet here
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatExample {
public static void main(String[] args) {
Date date = new Date();
int days = 5;
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
String strDate= formatter.format(date.getTime() + (days*86400000));
System.out.println(strDate);
}
}
to add n no. of days to today's date. The result will be correct upto n=24 but gives previous month' after n=24. Why it is so?
The problem is the the int is overflowing
consider
int days = 25;
int d = days*86400000;
System.out.println(d);
try
int days = 25;
long d = days*86400000L;
System.out.println(d);
tl;dr
LocalDate // Represent a date-only, without a time-of-day and without a time zone.
.now() // Capture the current date, as seen through your JVM’s current default time zone. Better to pass a `ZoneId` as the optional argument.
.plusDays( 5 ) // Add five days, returning a new `LocalDate` object. Per the Immutable Objects pattern, a new object is produced rather than changing (“mutating”) the original.
.format( // Generate text representing the date value of our `LocalDate` object.
DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) // Define a formatting pattern to suit your taste. Or call the `.ofLocalized…` methods to localize automatically.
) // Returns a `String`.
java.time
Date class represents a moment in UTC, a date with a time-of-day, and an offset-from-UTC of zero. Wrong class to use when working with date-only values.
Avoid using the terrible old legacy date-time classes such as Calendar, Date, and SimpleDateFormat. These classes were supplanted years ago by the java.time classes.
Do not track days as a count of seconds or milliseconds. Days are not always 24 hours long, and years are not always 365 days long.
LocalDate
Instead, use LocalDate class.
LocalDate today = LocalDate.now() ;
LocalDate later = today.plusDays( 5 ) ;
Convert
Best to avoid the legacy classes altogether. But if you must interoperate with old code not yet updated to java.time classes, you can convert back-and-forth. Call new methods added to the old classes.
For Date you need to add a time-of-day. I expect you will want to go with the first moment of the day. And I'll assume you want to frame the date as UTC rather than a time zone. We must go through a OffsetDateTime object to add the time-of-day and offset. For the offset, we use the constant ZoneOffset.UTC. Then we extract the more basic Instant class object to convert to a java.util.Date.
OffsetDateTime odt = OffsetDateTime.of( later , LocalTime.MIN , ZoneOffset.UTC ) ; // Combine the date with time-of-day and with an offset-from-UTC.
Instant instant = odt.toInstant() ; // Convert to the more basic `Instant` class, a moment in UTC, always UTC by definition.
java.util.Date d = java.util.Date.from( instant ) ; // Convert from modern class to legacy class.
Going the other direction:
Instant instant = d.toInstant() ; // Convert from legacy class to modern class.
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.
Use days*86400000L to make this a long calculation otherwise the int value overflows.
Try this one in your code:
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DATE, 5);
strDate = formatter.format(cal.getTime());

Converting Date to 08:00:00.000+0000

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

How to convert UTC Date String and remove the T and Z in Java?

Am using Java 1.7.
Trying to convert:
2018-05-23T23:18:31.000Z
into
2018-05-23 23:18:31
DateUtils class:
public class DateUtils {
public static String convertToNewFormat(String dateStr) throws ParseException {
TimeZone utc = TimeZone.getTimeZone("UTC");
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
sdf.setTimeZone(utc);
Date convertedDate = sdf.parse(dateStr);
return convertedDate.toString();
}
}
When trying to use it:
String convertedDate = DateUtils.convertToNewFormat("2018-05-23T23:18:31.000Z");
System.out.println(convertedDate);
Get the following exception:
Exception in thread "main" java.text.ParseException: Unparseable date: "2018-05-23T23:22:16.000Z"
at java.text.DateFormat.parse(DateFormat.java:366)
at com.myapp.utils.DateUtils.convertToNewFormat(DateUtils.java:7)
What am I possibly doing wrong?
Is there an easier way to do is (e.g. Apache Commons lib)?
tl;dr
Instant.parse( "2018-05-23T23:18:31.000Z" ) // Parse this String in standard ISO 8601 format as a `Instant`, a point on the timeline in UTC. The `Z` means UTC.
.atOffset( ZoneOffset.UTC ) // Change from `Instant` to the more flexible `OffsetDateTime`.
.format( // Generate a String representing the value of this `OffsetDateTime` object.
DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" ) // Specify a formatting pattern as desired.
) // Returns a `String` object.
2018-05-23 23:18:31
ISO 8601
Your input string is in standard ISO 8601 format.
The java.time classes use these standard formats by default when parsing/generating strings.
The T separates the year-month-day portion from the hour-minute-second. The Z is pronounced Zulu and means UTC.
java.time
You are using troublesome old date-time classes that were supplanted years ago by the java.time classes. The Apache DateUtils is also no longer needed, as you will find its functionality in java.time as well.
Parse that input string as a Instant object. 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).
String input = "2018-05-23T23:18:31.000Z" ;
Instant instant = Instant.parse( input ) ;
To generate a string in another format, we need a more flexible object. The Instant class is meant to be a basic building block. Lets convert it to a OffsetDateTime`, using UTC itself as the specified offset-from-UTC.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
Define a formatting pattern to match your desired output.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" ) ;
String output = odt.format( f ) ;
Tip: Consider using DateTimeFormatter::ofLocalized… methods to automatically localize the String generation per some Locale rather than hard-coding a formatting pattern.
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. Hibernate 5 & JPA 2.2 support java.time.
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 brought 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 (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
Try this. You have to use one pattern for parsing and another for formatting.
public static String convertToNewFormat(String dateStr) throws ParseException {
TimeZone utc = TimeZone.getTimeZone("UTC");
SimpleDateFormat sourceFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
SimpleDateFormat destFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sourceFormat.setTimeZone(utc);
Date convertedDate = sourceFormat.parse(dateStr);
return destFormat.format(convertedDate);
}
For others without Java 1.7 Restrictions:
Since Java 1.8 you can do it using LocalDateTime and ZonedDateTime from the package java.time
public static void main(String[] args) {
String sourceDateTime = "2018-05-23T23:18:31.000Z";
DateTimeFormatter sourceFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
DateTimeFormatter targetFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(sourceDateTime, sourceFormat);
String formatedDateTime = dateTime.atZone(ZoneId.of("UTC")).format(targetFormat);
System.out.println(formatedDateTime);
}
EDIT: (see Comments)
Quote from the Oracle Java documentation of LocalDateTime:
LocalDateTime is an immutable date-time object that represents a
date-time, often viewed as year-month-day-hour-minute-second. Other
date and time fields, such as day-of-year, day-of-week and
week-of-year, can also be accessed. Time is represented to nanosecond
precision. For example, the value "2nd October 2007 at
13:45.30.123456789" can be stored in a LocalDateTime.
This class does not store or represent a time-zone. Instead, it is a
description of the date, as used for birthdays, combined with the
local time as seen on a wall clock. It cannot represent an instant on
the time-line without additional information such as an offset or
time-zone.
the OP is asking to JUST parsing an Input String to a date-time (as year-month-day-hour-minute-second) and the Documentation says
LocalDateTime ... represents a date-time, often viewed as
year-month-day-hour-minute-second
so no important information are lost here. And the part dateTime.atZone(ZoneId.of("UTC")) returns a ZonedDateTime so the ZimeZone is handled at this point again if the user needs to work with the timezone ...etc.
so don't try to force users to use the "One and Only" solution you present in your answer.
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API.
Also, quoted below is a notice from the Home Page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Solution using java.time, the modern Date-Time API:
ZonedDateTime.parse("2018-05-23T23:18:31.000Z")
.format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH));
ONLINE DEMO
Note that you do not need a custom DateTimeFormatter to parse the date-time string, 2018-05-23T23:18:31.000Z as it is already in the default pattern used by ZonedDateTime. The modern date-time API is based on ISO 8601.
Learn more about the modern Date-Time API from Trail: Date Time.
Some helpful answers using java.time API:
'Z' is not the same as Z.
Never use SimpleDateFormat or DateTimeFormatter without a Locale.
I prefer u to y with a DateTimeFormatter.
For the sake of completeness
For the sake of completeness, given below is a solution using the legacy date-time API:
DateFormat parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.ENGLISH);
parser.setTimeZone(TimeZone.getTimeZone("UTC"));
Date dateTime = parser.parse("2018-05-23T23:18:31.000Z");
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
formatter.setTimeZone(parser.getTimeZone());
String formattedDateTimeString = formatter.format(dateTime);
System.out.println(formattedDateTimeString);
ONLINE DEMO
YYYY does not match with year part. In java 7 you need yyyy.
For T, use 'T' to match it
You're also missing the faction of millsecond part: .SSS
Try this:
String dateStr="2018-05-23T23:18:31.000Z";
TimeZone utc = TimeZone.getTimeZone("UTC");
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss.SSS'Z'");
sdf.setTimeZone(utc);
Date convertedDate = sdf.parse(dateStr);
convertedDate.toString();
In Kotlin and using ThreeTenABP,
fun getIsoString(year: Int, month: Int, day: Int): String {
val localTime = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, ZoneId.of("Z"))
val utcTime = localTime.toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC)
val isoString = utcTime.toInstant().toString() // 1940-15-12T00:00:00Z
val formattedIsoString = val formattedIsoString =
Instant.parse(isoString)
.atOffset(ZoneOffset.UTC)
.format(DateTimeFormatter
.ofPattern("uuuu-MM-dd'T'HH:mm:ss")) // 'T' in quotes so that it is retained.
return formattedIsoString
}
// print it
print(getIsoString(1940, 15, 12)) // 1940-15-12T00:00:00
You can try this below the idea.
I am not an expert in JAVA but I did it in javascript/node.js
import * as momentTimeZone from 'moment-timezone';
let d = new Data(); // d = '2018-05-23T23:18:31.000Z'; or we can take this date
let finalOutput = momentTimeZone(d).tz(this.locationService.locationTimeZone).utc().format('YYYY-MM-DD HH:mm:ss');
console.log('Result: ', finalOutput); // Result: "2018-05-23 23:18:31";
It also works with moment.js.
Here is more about format.

How do I parse RFC 3339 datetimes with Java?

I'm trying to parse the date returned as a value from the HTML5 datetime input field. Try it in Opera to see an example. The date returned looks like this: 2011-05-03T11:58:01Z.
I'd like to parse that into a Java Date or Calendar Object.
Ideally a solution should have the following things:
No external libraries (jars)
Handles all acceptable RFC 3339 formats
A String should be able to be easily validated to see if it is a valid RFC 3339 date
tl;dr
Instant.parse( "2011-05-03T11:58:01Z" )
ISO 8601
Actually, RFC 3339 is but a mere self-proclaimed “profile” of the actual standard, ISO 8601.
The RFC is different in that it purposely violates ISO 8601 to allow a negative offset of zero hours (-00:00) and gives that a semantic meaning of “offset unknown“. That semantic seems like a very bad idea to me. I advise sticking with the more sensible ISO 8601 rules. In ISO 8601, having no offset at all means the offset is unknown – an obvious meaning, whereas the RFC rule is abstruse.
The modern java.time classes use the ISO 8601 formats by default when parsing/generating strings.
Your input string represents a moment in UTC. The Z on the end is short for Zulu and means UTC.
Instant (not Date)
The modern class Instant represents a moment in UTC. This class replaces java.util.Date, and uses a finer resolution of nanoseconds rather than milliseconds.
Instant instant = Instant.parse( "2011-05-03T11:58:01Z" ) ;
ZonedDateTime (not Calendar)
To see that same moment through the wall-clock time used by the people of a certain region (a time zone), apply a ZoneId to get a ZonedDateTime. This class ZonedDateTime replaces the java.util.Calendar class.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same moment, same point on the timeline, different wall-clock time.
Converting
I strongly recommend avoiding the legacy date-time classes when possible. But if you must inter-operate with old code not yet updated to java.time, you may convert back-and-forth. Call new methods added to the old classes.
Instant replaces java.util.Date.
java.util.Date myJUDate = java.util.Date.from( instant ) ; // From modern to legacy.
Instant instant = myJUDate.toInstant() ; // From legacy to modern.
ZonedDateTime replaces GregorianCalendar.
java.util.GregorianCalendar myGregCal = java.util.GregorianCalendar.from( zdt ) ; // From modern to legacy.
ZonedDateTime zdt = myGregCal.toZonedDateTime() ; // From legacy to modern.
If you have a java.util.Calendar that is actually a GregorianCalendar, cast.
java.util.GregorianCalendar myGregCal = ( java.util.GregorianCalendar ) myCal ; // Cast to the concrete class.
ZonedDateTime zdt = myGregCal.toZonedDateTime() ; // From legacy to modern.
Bulleted concerns
Regarding your Question’s specific issues…
No external libraries (jars)
The java.time classes are built into Java 8, 9, 10, and later. An implementation is also included in later Android. For earlier Java and earlier Android, see the next section of this Answer.
Handles all acceptable RFC 3339 formats
The various java.time classes handle every ISO 8601 format I know of. They even handle some formats that mysteriously disappeared from later editions of the standard.
For other formats, see the parse and toString methods of the various classes such as LocalDate, OffsetDateTime, and so on. Also, search Stack Overflow as there are many examples and discussions on this topic.
A String should be able to be easily validated to see if it is a valid RFC 3339 date
To validate input strings, trap for DateTimeParseException.
try {
Instant instant = Instant.parse( "2011-05-03T11:58:01Z" ) ;
} catch ( DateTimeParseException e ) {
… handle invalid input
}
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.
So, in principle this would be done using different SimpleDateFormat patterns.
Here a list of patterns for the individual declarations in RFC 3339:
date-fullyear: yyyy
date-month: MM
date-mday: dd
time-hour: HH
time -minute: mm
time-second: ss
time-secfrac: .SSS (S means millisecond, though - it is not clear what would happen if there are more or less than 3 digits of these.)
time-numoffset: (like +02:00 seems to be not supported - instead it supports the formats +0200, GMT+02:00 and some named time zones using z and Z.)
time-offset: 'Z' (not supporting other time zones) - you should use format.setTimezone(TimeZone.getTimeZone("UTC")) before using this.)
partial-time: HH:mm:ss or HH:mm:ss.SSS.
full-time: HH:mm:ss'Z' or HH:mm:ss.SSS'Z'.
full-date: yyyy-MM-dd
date-time: yyyy-MM-dd'T'HH:mm:ss'Z' or yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
As we can see, this seems not to be able to parse everything. Maybe it would be a better idea to implement an RFC3339DateFormat from scratch (using regular expressions, for simplicity, or parsing by hand, for efficiency).
Just found that google implemented Rfc3339 parser in Google HTTP Client Library
https://github.com/google/google-http-java-client/blob/dev/google-http-client/src/main/java/com/google/api/client/util/DateTime.java
Tested. It works well to parse varies sub seconds time fragment.
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import com.google.api.client.util.DateTime;
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.withZone(ZoneId.of("UTC"));
#Test
public void test1e9Parse() {
String timeStr = "2018-04-03T11:32:26.553955473Z";
DateTime dateTime = DateTime.parseRfc3339(timeStr);
long millis = dateTime.getValue();
String result = formatter.format(new Date(millis).toInstant());
assert result.equals("2018-04-03T11:32:26.553Z");
}
#Test
public void test1e3Parse() {
String timeStr = "2018-04-03T11:32:26.553Z";
DateTime dateTime = DateTime.parseRfc3339(timeStr);
long millis = dateTime.getValue();
String result = formatter.format(new Date(millis).toInstant());
assert result.equals("2018-04-03T11:32:26.553Z");
}
#Test
public void testEpochSecondsParse() {
String timeStr = "2018-04-03T11:32:26Z";
DateTime dateTime = DateTime.parseRfc3339(timeStr);
long millis = dateTime.getValue();
String result = formatter.format(new Date(millis).toInstant());
assert result.equals("2018-04-03T11:32:26.000Z");
}
With the format you have e.g. 2011-05-03T11:58:01Z, below code will do. However, I recently tryout html5 datetime in Chrome and Opera, it give me 2011-05-03T11:58Z --> do not have the ss part which cannot be handled by code below.
new Timestamp(javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar(date).toGregorianCalendar().getTimeInMillis());
Maybe not the most elegant way, but certainly working one I recently made:
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
cal.setTime(sdf.parse(dateInString.replace("Z", "").replace("T", "-")));
Though, The question is very old, but it may help one who wants it Kotlin version of this answer. By using this file, anyone can convert a Rfc3339 date to any date-format. Here I take a empty file name DateUtil and create a function called getDateString() which has 3 arguments.
1st argument : Your input date
2nd argument : Your input date pattern
3rd argument : Your wanted date pattern
DateUtil.kt
object DatePattern {
const val DAY_MONTH_YEAR = "dd-MM-yyyy"
const val RFC3339 = "yyyy-MM-dd'T'HH:mm:ss'Z'"
}
fun getDateString(date: String, inputDatePattern: String, outputDatePattern: String): String {
return try {
val inputFormat = SimpleDateFormat(inputDatePattern, getDefault())
val outputFormat = SimpleDateFormat(outputDatePattern, getDefault())
outputFormat.format(inputFormat.parse(date))
} catch (e: Exception) {
""
}
}
And now use this method in your activity/fuction/dataSourse Mapper to get Date in String format like this
getDate("2022-01-18T14:41:52Z", RFC3339, DAY_MONTH_YEAR)
and output will be like this
18-01-2022
For future reference, as an alternative, you could use ITU[1] which is hand-written to deal with exactly RFC-3339 parsing and also lets you easily deal with leap seconds. The library is dependency-free and only weighs in at 18 kB.
Full disclosure: I'm the author
try
{
final OffsetDateTime dateTime = ITU.parseDateTime(dateTimeStr);
}
catch (LeapSecondException exc)
{
// The following helper methods are available let you decide how to progress
//int exc.getSecondsInMinute()
//OffsetDateTime exc.getNearestDateTime()
//boolean exc.isVerifiedValidLeapYearMonth()
}
[1] - https://github.com/ethlo/itu
I'm using this:
DateTimeFormatter RFC_3339_DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
.append(ISO_LOCAL_DATE_TIME)
.optionalStart()
.appendOffset("+HH:MM", "Z")
.optionalEnd()
.toFormatter();
Example:
String dateTimeString = "2007-05-01T15:43:26.3452+07:00";
ZonedDateTime zonedDateTime = ZonedDateTime.from(RFC_3339_DATE_TIME_FORMATTER.parse(dateTimeString));
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(datetimeInFRC3339format)

how to convert timestamp string to java.util.Date

I need to convert a timestamp string to java.util.Date. E.g.:
MMDDYYHHMMSS to MM-DD-YY HH-MM-SS
Where MM is month, DD is date, YY is year, HH is hours, MM is minutes and SS is seconds.
You can do it like this:
DateFormat format = new SimpleDateFormat("MMddyyHHmmss");
Date date = format.parse("022310141505");
but I would strongly recommend that you use Joda Time instead. It's a better date/time library by a long, long way. In particular, the formatters/parsers in Joda Time are thread-safe, so you can reuse them freely and statically; java.text.SimpleDateFormat isn't thread-safe, so you either need to create one per thread or serialize access to it with a synchronized block.
tl;dr
java.time.LocalDateTime.parse(
"012318123456" ,
DateTimeFormatter.ofPattern( "MMdduuHHmmss" )
).format(
DateTimeFormatter.ofPattern( "MM-dd-uu HH-mm-ss" )
)
01-23-18 12-34-56
java.time
The modern approach uses the java.time classes.
Define a formatting pattern to match your input string.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MMdduuHHmmss" ) ;
Your two-digit year will be interpreted as being 21st century ( 20xx ).
Parse as a LocalDateTime because your input string lacks any indicator of time zone or offset-from-UTC.
LocalDateTime ldt = LocalDateTime.parse( "012318123456" , f ) ;
ldt.toString(): 2018-01-23T12:34:56
Generate a string in your desired format.
DateTimeFormatter fOut = DateTimeFormatter.ofPattern( "MM-dd-uu HH-mm-ss" ) ;
String output = ldt.format( fOut );
01-23-18 12-34-56
ISO 8601
Both of your formats are terrible, for multiple reasons.
When serializing date-time values, use the standard ISO 8601 formats whenever possible. They are designed to be practical, easy to parse by machine, easy to read by humans across cultures.
For a date-time time such as yours, the T in the middle separates the date portion from the time-of-day portion.
2018-01-23T12:34:56
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, 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.
use a SimpleDateFormat with an appropriate format string (be careful to use the correct format letters, uppercase and lowercase have different meanings!).

Categories

Resources