Improper date Conversion in Java from LocalDateTime to joda DateTime - java

I am taking input in the java.time.LocalDateTime format as I need hours/minutes.
input : 2020-04-19T01:03:50
To interact with oracle DB from jpaRepostory, I am using
import org.joda.time.DateTime;
List<String> findApps(#Param("lastModifiedDate") DateTime lastModifiedDate);
For conversion from LocalDate to dateTime I am using this way
DateTime.parse(startDate.toString(), DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss"))
But I am getting this result and unable to fetch any records.
2020-04-19T01:03:50.000+05:30
Can anyone help me.
PS: Thank you in advance.

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:
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
public class Main {
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.parse("2020-04-19T01:03:50");
OffsetDateTime odtIndia = ldt.atZone(ZoneId.of("Asia/Kolkata")).toOffsetDateTime();
System.out.println(odtIndia);
OffsetDateTime odtUtc = odtIndia.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(odtUtc);
}
}
Output:
2020-04-19T01:03:50+05:30
2020-04-18T19:33:50Z
ONLINE DEMO
The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).
Learn more about the modern Date-Time API from Trail: Date Time.
Using Joda API:
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
public class Main {
public static void main(String[] args) {
LocalDateTime ldt = new LocalDateTime("2020-04-19T01:03:50");
DateTime dtIndia = ldt.toDateTime(DateTimeZone.forID("Asia/Kolkata"));
System.out.println(dtIndia);
DateTime dtUtc = dtIndia.toDateTime(DateTimeZone.UTC);
System.out.println(dtUtc);
}
}
Output:
2020-04-19T01:03:50.000+05:30
2020-04-18T19:33:50.000Z
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

You can try something like this
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class Joda {
public static void main(String[] args) {
DateTime startDate = new DateTime();
DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss");
String formatted = dtf.print(startDate); //prints 2021-06-26T17:32:50
System.out.println(formatted);
DateTime parsed = DateTime.parse(formatted, DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss"));
}
}

Related

Convert a timestamp to ISO format date string

I have a logic in python that I am converting into Java code.
The logic is I need to read from a timestamp attribute in JSON file and convert it into ISO date format.
Python query:
datetime.datetime.fromtimestamp(jsonMsg["time"]).isoformat(timespec='seconds')
Here is the code I wrote in Java
1627065646.444 is an example of the value I get from JSON script
long timestamp = (long) 1627065646.444 * 1000;
Timestamp time = new Timestamp(timestamp);
Date d = new Date(time.getTime());
DateFormat df = new SimpleDateFormat();
String dateToString = df.format(d);
LocalDateTime datetime = LocalDateTime.parse(dateToString, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
ZoneOffset offset = ZoneOffset.UTC;
String formattedTimeStamp = datetime.atOffset(offset).toString();
When I run the code I get compile error "Text '7/23/21 11:40 AM' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0"
This exception occurs at LocalDateTime.parse(dateToString, DateTimeFormatter.ISO_LOCAL_DATE_TIME. Can someone please help me in understanding what I am doing wrong here.
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*.
Solution using java.time, the modern Date-Time API:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
long timestamp = (long) (1627065646.444 * 1000);
Instant instant = Instant.ofEpochMilli(timestamp);
System.out.println(instant);
ZonedDateTime zdt = instant.atZone(ZoneOffset.UTC);
LocalDateTime ldt = zdt.toLocalDateTime();
System.out.println(ldt);
// A custom format
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("M/d/u h:m:s a", Locale.ENGLISH);
String formatted = dtf.format(zdt);
System.out.println(formatted);
}
}
Output:
2021-07-23T18:40:46.444Z
2021-07-23T18:40:46.444
7/23/2021 6:40:46 PM
ONLINE DEMO
The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).
Learn more about the modern Date-Time API* from Trail: Date Time.
Apart from this, what else is wrong with your code?
You have done
long timestamp = (long) 1627065646.444 * 1000;
in which 1627065646.444 will be cast to long resulting in 1627065646 and thus the result of the multiplication will be 1627065646000, not 1627065646444 what you are expecting. You need to cast to long after performing the multiplication.
A valuable comment by Ole V.V.:
I’d use Math.round(1627065646.444 * 1000) to make sure that
floating-point inaccuracy is handled.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Set date and time in java.sql.Timestamp

Please tell me how to set the date (current date minus one day) and time equal to 19:00:00 using such a construction?
new java.sql.Timestamp(java.util.Calendar.getInstance.getTime().getTime())
LocalDateTime don't use.
I recommend you do it using the java.time (the modern date-time API).
Solution, purely using the modern API:
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
OffsetDateTime odt = ZonedDateTime.now(ZoneId.systemDefault())
.minusDays(1)
.with(LocalTime.of(19, 0))
.toOffsetDateTime();
System.out.println(odt);
}
}
Output:
2020-12-24T19:00Z
You can use the OffsetDateTime in your JDBC code as follows:
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, odt);
st.executeUpdate();
st.close();
However, if you still want to use java.sql.Timestamp, you can use ZonedDateTime with the applicable timezone to get the required date-time and then convert it into Instant from which you can get Epoch milliseconds. You can Finally use the Epoch milliseconds to construct an instance of java.sql.Timestamp.
import java.sql.Timestamp;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.systemDefault())
.minusDays(1)
.with(LocalTime.of(19, 0));
Timestamp timestamp = new Timestamp(zdt.toInstant().toEpochMilli());
System.out.println(timestamp);
}
}
Output:
2020-12-24 19:00:00.0
Notes:
I have used ZoneId.systemDefault() which uses the JVM's timezone. Change it to applicable timezone e.g. ZoneId.of("Europe/London").
Instant belongs to the modern date-time API. Learn about the modern date-time API from Trail: Date Time.
For whatsoever reason if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Solution, purely using the legacy API:
import java.sql.Timestamp;
import java.util.Calendar;
public class Main {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, -1);
calendar.set(Calendar.HOUR_OF_DAY, 19);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Timestamp timestamp = new Timestamp(calendar.getTimeInMillis());
System.out.println(timestamp);
}
}
Output:
2020-12-24 19:00:00.0
This is my code
Set date to yesterday with Calendar.add(Calendar.DAY_OF_YEAR, -1)
Compare hour with Calendar.get(Calendar.HOUR_OF_DAY)
getHour of java.sql.Timestamp is Deprecated.
replaced by Calendar.get(Calendar.HOUR_OF_DAY).
import java.sql.Timestamp;
import java.util.Calendar;
Calendar calendar = Calendar.getInstance(); // 2020-12-25 19:42:57.739
calendar.add(Calendar.DAY_OF_YEAR, -1);
Timestamp timestamp = new Timestamp(calendar.getTimeInMillis());
System.out.println(timestamp); // 2020-12-24 19:42:57.739
System.out.println(19 == calendar.get(Calendar.HOUR_OF_DAY)); // true
Bye!

Conversion from UTC to IST returning same value in JAVA using Joda time library

I need to convert TimeZone in my project from UTC to IST and vice versa. For that purpose I am using Joda time jar in my project. But the problem occurs when I try to convert the string from UTC to IST, I am getting the same value instead of getting converted IST value. Kindly please mentor me in which part of code I am completely stuck up. My code is as follows:
public class JodaDemo {
public static final String DATE_PATTERN_SERVICE = "yyyy-MM-dd HH:mm:ss";
public static final String DATE_PATTERN_SERVICE_NO_SECONDS = "yyyy-MM-dd HH:mm";
public static void main(String[] args) {
getDateFromUTCtoIST("2015-08-23 10:34:40");
}
private static void getDateFromUTCtoIST(String dateTime) {
DateTimeFormatter dtf = DateTimeFormat.forPattern(DATE_PATTERN_SERVICE);
DateTime jodatime = dtf.parseDateTime(dateTime);
DateTimeZone indianTimeZone = DateTimeZone.forID("Asia/Kolkata");
DateTime indianTime = jodatime.withZone(indianTimeZone);
System.out.println(indianTime);
}
OUTPUT:
2015-08-23T10:34:40.000+05:30
Expected output:
Converted TimeZone (+5:30 output) like in yyyy-MM-dd HH:mm:ss format
There are two problems here. Firstly, when you're parsing the value you're not specifying the time zone - so it's using your local time zone. Secondly, you're not using any formatter for the result - you're just calling DateTime.toString(), implicitly.
The simplest approach is actually to create two formatters for the same pattern, one in UTC and one in the relevant time zone - then you don't need to manually convert at all, as the formatter can do it for you:
import java.util.*;
import org.joda.time.*;
import org.joda.time.format.*;
public class Test {
public static final String DATE_PATTERN_SERVICE = "yyyy-MM-dd HH:mm:ss";
public static void main(String[] args) {
DateTimeFormatter utcFormatter = DateTimeFormat
.forPattern(DATE_PATTERN_SERVICE)
.withLocale(Locale.US)
.withZoneUTC();
DateTimeZone indianZone = DateTimeZone.forID("Asia/Kolkata");
DateTimeFormatter indianZoneFormatter = utcFormatter.withZone(indianZone);
String utcText = "2015-08-23 10:34:40";
DateTime parsed = utcFormatter.parseDateTime(utcText);
String indianText = indianZoneFormatter.print(parsed);
System.out.println(indianText); // 2015-08-23 16:04:40
}
}
java.time
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:
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
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) {
String strDateTime = "2015-08-23 10:34:40";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime, parser);
ZonedDateTime zdtUtc = ldt.atZone(ZoneId.of("Etc/UTC"));
ZonedDateTime zdtIndia = zdtUtc.withZoneSameInstant(ZoneId.of("Asia/Kolkata"));
System.out.println(zdtIndia);
OffsetDateTime odt = zdtIndia.toOffsetDateTime();
System.out.println(odt);
}
}
Output:
2015-08-23T16:04:40+05:30[Asia/Kolkata]
2015-08-23T16:04:40+05:30
ONLINE DEMO
Some important notes:
If you are going to deal with JDBC, check this answer and this answer to learn how to use java.time API with JDBC.
For any reason, if you need to convert this object of OffsetDateTime to an object of java.util.Date, you can do so as follows:
Date date = Date.from(odt.toInstant());
Learn more about the modern Date-Time API from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Custom String from ISO Compliant Date

I am getting a date string as 2014-01-11-T00:00:00Z
I want to convert this date to 20140111 i.e YYYYMMDD it should be a string.
Any standard method/function to achieve above?
java.time
Your date-time string, 2014-01-11-T00:00:00Z is a bit weird as I have never seen such a date-time string where there is a hyphen (-) before T. For this kind of string, the following pattern meets the parsing requirement:
yyyy-M-d-'T'H:m:sXXX
Also, with java.time API, I recommend you replace y with u as explained in this answer. For the output string, you do NOT need to define any pattern as there already exists an inbuilt DateTimeFormatter for this pattern: DateTimeFormatter.BASIC_ISO_DATE.
Demo:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String args[]) {
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d-'T'H:m:sXXX", Locale.ENGLISH);
OffsetDateTime odt = OffsetDateTime.parse("2014-01-11-T00:00:00Z", dtfInput);
System.out.println(odt);
String output = odt.toLocalDate().format(DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(output);
}
}
Output:
2014-01-11T00:00Z
20140111
Note:
Had your date-time string been ISO 8601 compliant, you would NOT have needed to use a DateTimeFormatter object explicitly for parsing i.e. you could have simply parsed it as
OffsetDateTime odt = OffsetDateTime.parse("2014-01-11T00:00:00Z");
The Z in the date-time stands for Zulu which specifies UTC time (that has a timezone offset of +00:00 hours) in ISO 8601 standard. Thus, this solution will also work for a date-time string like 2014-01-11-T00:00:00+02:00 which has a timezone offset of +02:00 hours.
In case, you need a java.util.Date object from this object of OffsetDateTime, you can do so as follows:
Date date = Date.from(odt.toInstant());
Learn more about the the modern date-time API* from Trail: Date Time.
Note that the legacy date-time API (java.util date-time types and their formatting API, SimpleDateFormat) are outdated and error-prone. It is recommended to stop using them completely and switch to java.time API. Just for the sake of completeness, I am providing you with a solution using the legacy API.
Using the legacy API:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String args[]) throws ParseException {
SimpleDateFormat sdfInput = new SimpleDateFormat("yyyy-M-d-'T'H:m:sXXX", Locale.ENGLISH);
SimpleDateFormat sdfOutput = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
sdfOutput.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));// Change it as required
Date date = sdfInput.parse("2014-01-11-T00:00:00Z");
String output = sdfOutput.format(date);
System.out.println(output);
}
}
Output:
20140111
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Take this
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormat {
public static void main(String[] args) throws ParseException {
SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd-'T'HH:mm:ss'Z'");
Date inDate = inFormat.parse("2014-01-11-T00:00:00Z");
SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMdd");
String output = outFormat.format(inDate);
System.out.println("Date: " + output);
}
}
Take a look at this thread for Date formatting in Java using Zoulou notation :
Converting ISO 8601-compliant String to java.util.Date
Then create a new SimpleDateFormat using the "yyyyMMdd" format string.
Here an improved version of given answer by #drkunibar:
SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd-'T'HH:mm:ss'Z'");
inFormat.setTimeZone(TimeZone.getTimeZone("GMT")); // Z denotes UTC in ISO-8601
Date inDate = inFormat.parse("2014-01-11-T00:00:00Z");
SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMdd");
outFormat.setTimeZone(TimeZone.getTimeZone("...")); // set your timezone explicitly!
String output = outFormat.format(inDate);
System.out.println("Date: " + output);
Note that the format YYYYMMDD is also ISO-8601-compliant (a so-called basic calendar date). The question you have to ask yourself is in which timezone you want to get your output. If in UTC you have to set "GMT", too. Without setting timezone it can happen that your output date differs from input UTC date by one day dependent where your default system timezone is (for example US is several hours behind UTC, in this case one calendar day before UTC midnight).
Update: This Answer is now obsolete. See the modern solution using java.time in the Answer by Avinash.
Joda-Time
This date-time work is much easier with the Joda-Time 2.3 library.
String input = "2014-01-11T00:00:00Z"; // In standard ISO 8601 format.
DateTime dateTime = new DateTime( input, DateTimeZone.UTC ); // Parse string into date-time object.
DateTimeFormatter formatter = ISODateTimeFormat.basicDate(); // Factory to make a formatter.
String output = formatter.print( dateTime ); // Generate string from date-Time object.

Convert to date

I'm trying to create number of Evenement instances and set the date for them:
for (int i=2004; i<2009; i++){
evenementen.add(new Evenement("Rock Werchter", "Rock", "Werchter", 200000,
(Date)formatter.parse(i+"/07/03")));
But I can't seem to get it to work,
Any ideas?
You may want to use Calendar to create your dates.
for (int i=2004; i<2009; i++) {
Calendar cal = Calendar.getInstance();
cal.clear();
// Calendar.JULY may be different depending on the JDK language
cal.set(i, Calendar.JULY, 3); // Alternatively, cal.set(i, 6, 3);
evenementen.add(new Evenement("Rock Werchter", "Rock", "Werchter", 200000,
cal.getTime()));
}
Note that the months are zero-based, so July is 6.
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*.
Solution using java.time, the modern API:
import java.time.LocalDate;
import java.time.Month;
public class Main {
public static void main(String[] args) {
for (int i = 2004; i < 2009; i++) {
System.out.println(LocalDate.of(i, Month.JULY, 3));
}
}
}
If you want to do it by parsing the string (the way you have posted in the question), use DateTimeFormatter.
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u/M/d", Locale.ENGLISH);
for (int i = 2004; i < 2009; i++) {
LocalDate date = LocalDate.parse(i + "/07/03", dtf);
System.out.println(date);
}
}
}
Output:
2004-07-03
2005-07-03
2006-07-03
2007-07-03
2008-07-03
Learn more about java.time, the modern Date-Time API* from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Beware of the locale used for the date formatter (default can be Locale.ENGLISH is your OS is set that way, meaning the year is at the end, not at the beginning of the string)
You need to be sure to have a formatter build as (at the time of writing, 2008, Java6, as in this answer):
formatter = new SimpleDateFormat("yyyy/MM/DD");

Categories

Resources