Java Convert String and Long to DateTime - java

I would like to generate a DateTime variable from two different variables (get the date from myLongDateAndTime and time from myStringTime, how can I do that?
String myStringTime="12:30:10"; // Come from DB
long myLongDateAndTime= 1628197200000 // Come from another DB stores date and times in timestamp format of Thu Aug 05 2021 17:00:00 GMT-0400
DateTime myDateTime=??? // should get Thu Aug 05 2021 12:30:10

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.Instant;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class Main {
public static void main(String[] args) {
String myStringTime = "12:30:10";
long myLongDateAndTime = 1628197200000L;
LocalTime time = LocalTime.parse(myStringTime);
System.out.println(time);
Instant instant = Instant.ofEpochMilli(myLongDateAndTime);
System.out.println(instant);
OffsetDateTime odt = instant.atOffset(ZoneOffset.of("-04:00"));
System.out.println(odt);
odt = odt.with(time);
System.out.println(odt);
}
}
Output:
12:30:10
2021-08-05T21:00:00Z
2021-08-05T17:00-04:00
2021-08-05T12:30:10-04:00
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
Just for the sake of completeness
Just for the sake of completeness, given below is the solution using the Joda Date-Time API:
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalTime;
public class Main {
public static void main(String[] args) {
String myStringTime = "12:30:10";
long myLongDateAndTime = 1628197200000L;
LocalTime time = LocalTime.parse(myStringTime);
System.out.println(time);
DateTime dateTime = new DateTime(Long.valueOf(myLongDateAndTime), DateTimeZone.forOffsetHours(-4));
System.out.println(dateTime);
dateTime = dateTime.withTime(time);
System.out.println(dateTime);
}
}
Output:
12:30:10.000
2021-08-05T17:00:00.000-04:00
2021-08-05T12:30:10.000-04:00
* 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 are combining two dates, so what you need to do is:
create a joda DateTime from the long
format that DateTime to a string with only the date part
combine with date string and time string in a single string
parse the new string
and here is how you can do that:
public DateTime combineDates(long myLongDateAndTime, String myStringTime) {
// 1 - create DateTime from the long
DateTime dateFromLong = new DateTime(myLongDateAndTime);
// 2 - Format dateFromLong as date string
DateTimeFormatter dtfDate = DateTimeFormat.forPattern("dd/MM/yyyy");
String dateString = dtfDate.print(dateFromLong);
// 3 - Concatenate date part and time part in a new string
String completeDate = dateString + " " + myStringTime;
// 4 - Parse the new string in to a DateTime
DateTimeFormatter dtfDateTime =
DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");
return dtfDateTime.parseDateTime(completeDate);
}
This is only a possible solution. There are many other ways to do the same, for example without using a string concatenation, but only dates operations, but this way is quite clear and readable, so I don't investigate additional possible solutions.

One possible solution:
public class TestSample {
public static void main(String[] args) {
String myStringTime="12:30:10";
Long myLongDateAndTime= 1628197200000L;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss", Locale.ENGLISH);
LocalTime time = LocalTime.parse(myStringTime, formatter);
LocalDate date = Instant.ofEpochMilli(myLongDateAndTime).atZone(ZoneId.of("UTC")).toLocalDate();
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
LocalDateTime dtTime = LocalDateTime.parse(date.toString()+" "+time.toString(), formatter1);
System.out.println(dtTime.toString());
}
}

Related

How to add 'T' to UTC timestamp without T and also add 5 mins to it

I wan to convert the string d (date in UTC format) to String in UTC format with 'T' and increment 5 mins to time. Below is the code
public static void main (String args[]) throws ParseException
{
String d="2021-08-27 06:25:00.716241+00:00";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSXXX");
SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date actualDate = format.parse(d);
String a=format1.format(actualDate);
System.out.println(a);
}
I get output as 2021-08-27T12:06:56 but I need String 'a' as 2021-08-27T06:25:00 and then add 5 mins to it and make it 2021-08-27T06:30:00
Please help
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.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String d = "2021-08-27 06:25:00.716241+00:00";
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d H:m:s.SSSSSSXXX", Locale.ENGLISH);
OffsetDateTime odt = OffsetDateTime.parse(d, dtfInput);
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
String str = odt.format(dtfOutput);
System.out.println(str);
// Add 5 minutes to it
odt = odt.plusMinutes(5);
str = odt.format(dtfOutput);
System.out.println(str);
}
}
Output:
2021-08-27T06:25:00
2021-08-27T06:30:00
ONLINE DEMO
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.

Format ISO 8601 offset in Java [duplicate]

I have a date in the following format: 2010-03-01T00:00:00-08:00
I have thrown the following SimpleDateFormats at it to parse it:
private static final SimpleDateFormat[] FORMATS = {
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"), //ISO8601 long RFC822 zone
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz"), //ISO8601 long long form zone
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"), //ignore timezone
new SimpleDateFormat("yyyyMMddHHmmssZ"), //ISO8601 short
new SimpleDateFormat("yyyyMMddHHmm"),
new SimpleDateFormat("yyyyMMdd"), //birthdate from NIST IHE C32 sample
new SimpleDateFormat("yyyyMM"),
new SimpleDateFormat("yyyy") //just the year
};
I have a convenience method that uses those formats like so:
public static Date figureOutTheDamnDate(String wtf) {
if (wtf == null) {
return null;
}
Date retval = null;
for (SimpleDateFormat sdf : FORMATS) {
try {
sdf.setLenient(false)
retval = sdf.parse(wtf);
System.out.println("Date:" + wtf + " hit on pattern:" + sdf.toPattern());
break;
} catch (ParseException ex) {
retval = null;
continue;
}
}
return retval;
}
It seems to hit on the pattern yyyyMMddHHmm but returns the date as Thu Dec 03 00:01:00 PST 2009.
What is the correct pattern to parse this date?
UPDATE: I don't NEED the time zone parsing. I don't anticipate having time sensitive issues moving between zones, but how would I get the "-08:00" zone format to parse????
Unit test:
#Test
public void test_date_parser() {
System.out.println("\ntest_date_parser");
//month is zero based, are you effing kidding me
Calendar d = new GregorianCalendar(2000, 3, 6, 13, 00, 00);
assertEquals(d.getTime(), MyClass.figureOutTheDamnDate("200004061300"));
assertEquals(new GregorianCalendar(1950, 0, 1).getTime(), MyClass.figureOutTheDamnDate("1950"));
assertEquals(new GregorianCalendar(1997, 0, 1).getTime(), MyClass.figureOutTheDamnDate("199701"));
assertEquals(new GregorianCalendar(2010, 1, 25, 15, 19, 44).getTime(), MyClass.figureOutTheDamnDate("20100225151944-0800"));
//my machine happens to be in GMT-0800
assertEquals(new GregorianCalendar(2010, 1, 15, 13, 15, 00).getTime(),MyClass.figureOutTheDamnDate("2010-02-15T13:15:00-05:00"));
assertEquals(new GregorianCalendar(2010, 1, 15, 18, 15, 00).getTime(), MyClass.figureOutTheDamnDate("2010-02-15T18:15:00-05:00"));
assertEquals(new GregorianCalendar(2010, 2, 1).getTime(), MyClass.figureOutTheDamnDate("2010-03-01T00:00:00-08:00"));
assertEquals(new GregorianCalendar(2010, 2, 1, 17, 0, 0).getTime(), MyClass.figureOutTheDamnDate("2010-03-01T17:00:00-05:00"));
}
Output from unit test:
test_date_parser
Date:200004061300 hit on pattern:yyyyMMddHHmm
Date:1950 hit on pattern:yyyy
Date:199701 hit on pattern:yyyyMM
Date:20100225151944-0800 hit on pattern:yyyyMMddHHmmssZ
Date:2010-02-15T13:15:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
Date:2010-02-15T18:15:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
Date:2010-03-01T00:00:00-08:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
Date:2010-03-01T17:00:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
JodaTime's DateTimeFormat to rescue:
String dateString = "2010-03-01T00:00:00-08:00";
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
DateTimeFormatter dtf = DateTimeFormat.forPattern(pattern);
DateTime dateTime = dtf.parseDateTime(dateString);
System.out.println(dateTime); // 2010-03-01T04:00:00.000-04:00
(time and timezone difference in toString() is just because I'm at GMT-4 and didn't set locale explicitly)
If you want to end up with java.util.Date just use DateTime#toDate():
Date date = dateTime.toDate();
Wait for JDK7 (JSR-310) JSR-310, the referrence implementation is called ThreeTen (hopefully it will make it into Java 8) if you want a better formatter in the standard Java SE API. The current SimpleDateFormat indeed doesn't eat the colon in the timezone notation.
Update: as per the update, you apparently don't need the timezone. This should work with SimpleDateFormat. Just omit it (the Z) in the pattern.
String dateString = "2010-03-01T00:00:00-08:00";
String pattern = "yyyy-MM-dd'T'HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date date = sdf.parse(dateString);
System.out.println(date); // Mon Mar 01 00:00:00 BOT 2010
(which is correct as per my timezone)
if you used the java 7, you could have used the following Date Time Pattern. Seems like this pattern is not supported in the Earlier version of java.
String dateTimeString = "2010-03-01T00:00:00-08:00";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Date date = df.parse(dateTimeString);
For More information refer to the SimpleDateFormat documentation.
Here's a snippet I used - with plain SimpleDateFormat. Hope somebody else may benefit from it:
public static void main(String[] args) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") {
public StringBuffer format(Date date, StringBuffer toAppendTo, java.text.FieldPosition pos) {
StringBuffer toFix = super.format(date, toAppendTo, pos);
return toFix.insert(toFix.length()-2, ':');
};
};
// Usage:
System.out.println(dateFormat.format(new Date()));
}
Output:
- Usual Output.........: 2013-06-14T10:54:07-0200
- This snippet's Output: 2013-06-14T10:54:07-02:00
Or... better, use a simpler, different, pattern:
SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
// Usage:
System.out.println(dateFormat2.format(new Date()));
Output:
- This pattern's output: 2013-06-14T10:54:07-02:00
See the docs for that.
Try this, its work for me:
Date date = javax.xml.bind.DatatypeConverter.parseDateTime("2013-06-01T12:45:01+04:00").getTime();
In Java 8:
OffsetDateTime dt = OffsetDateTime.parse("2010-03-01T00:00:00-08:00");
If you can use JDK 1.7 or higher, try this:
public class DateUtil {
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
public static String format(Date date) {
return dateFormat.format(date);
}
public static Date parse(String dateString) throws AquariusException {
try {
return dateFormat.parse(dateString);
} catch (ParseException e) {
throw new AquariusException(e);
}
}
}
document: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
which supports a new Time Zone format "XXX" (e.g. -3:00)
While JDK 1.6 only support other formats for Time Zone, which are "z" (e.g. NZST), "zzzz" (e.g. New Zealand Standard Time), "Z" (e.g. +1200), etc.
tl;dr
OffsetDateTime.parse( "2010-03-01T00:00:00-08:00" )
Details
The answer by BalusC is correct, but now outdated as of Java 8.
java.time
The java.time framework is the successor to both Joda-Time library and the old troublesome date-time classes bundled with the earliest versions of Java (java.util.Date/.Calendar & java.text.SimpleDateFormat).
ISO 8601
Your input data string happens to comply with the ISO 8601 standard.
The java.time classes use ISO 8601 formats by default when parsing/generating textual representations of date-time values. So no need to define a formatting pattern.
OffsetDateTime
The OffsetDateTime class represents a moment on the time line adjusted to some particular offset-from-UTC. In your input, the offset is 8 hours behind UTC, commonly used on much of the west coast of North America.
OffsetDateTime odt = OffsetDateTime.parse( "2010-03-01T00:00:00-08:00" );
You seem to want the date-only, in which case use the LocalDate class. But keep in mind you are discarding data, (a) time-of-day, and (b) the time zone. Really, a date has no meaning without the context of a time zone. For any given moment the date varies around the world. For example, just after midnight in Paris is still “yesterday” in Montréal. So while I suggest sticking with date-time values, you can easily convert to a LocalDate if you insist.
LocalDate localDate = odt.toLocalDate();
Time Zone
If you know the intended time zone, apply it. A time zone is an offset plus the rules to use for handling anomalies such as Daylight Saving Time (DST). Applying a ZoneId gets us a ZonedDateTime object.
ZoneId zoneId = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = odt.atZoneSameInstant( zoneId );
Generating strings
To generate a string in ISO 8601 format, call toString.
String output = odt.toString();
If you need strings in other formats, search Stack Overflow for use of the java.util.format package.
Converting to java.util.Date
Best to avoid java.util.Date, but if you must, you can convert. Call the new methods added to the old classes such as java.util.Date.from where you pass an Instant. An Instant is a moment on the timeline in UTC. We can extract an Instant from our OffsetDateTime.
java.util.Date utilDate = java.util.Date( odt.toInstant() );
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, 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.
Thanks acdcjunior for your solution. Here's a little optimized version for formatting and parsing :
public static final SimpleDateFormat XML_SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.FRANCE)
{
private static final long serialVersionUID = -8275126788734707527L;
public StringBuffer format(Date date, StringBuffer toAppendTo, java.text.FieldPosition pos)
{
final StringBuffer buf = super.format(date, toAppendTo, pos);
buf.insert(buf.length() - 2, ':');
return buf;
};
public Date parse(String source) throws java.text.ParseException {
final int split = source.length() - 2;
return super.parse(source.substring(0, split - 1) + source.substring(split)); // replace ":" du TimeZone
};
};
You can use X in Java 7.
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
static final SimpleDateFormat DATE_TIME_FORMAT =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static final SimpleDateFormat JSON_DATE_TIME_FORMAT =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
private String stringDate = "2016-12-01 22:05:30";
private String requiredDate = "2016-12-01T22:05:30+03:00";
#Test
public void parseDateToBinBankFormat() throws ParseException {
Date date = DATE_TIME_FORMAT.parse(stringDate);
String jsonDate = JSON_DATE_TIME_FORMAT.format(date);
System.out.println(jsonDate);
Assert.assertEquals(jsonDate, requiredDate);
}
Try setLenient(false).
Addendum: It looks like you're recognizing variously formatted Date strings. If you have to do entry, you might like looking at this example that extends InputVerifier.
Since an example of Apache FastDateFormat(click for the documentations of versions:2.6and3.5) is missing here, I am adding one for those who may need it. The key here is the pattern ZZ(2 capital Zs).
import java.text.ParseException
import java.util.Date;
import org.apache.commons.lang3.time.FastDateFormat;
public class DateFormatTest throws ParseException {
public static void main(String[] args) {
String stringDateFormat = "yyyy-MM-dd'T'HH:mm:ssZZ";
FastDateFormat fastDateFormat = FastDateFormat.getInstance(stringDateFormat);
System.out.println("Date formatted into String:");
System.out.println(fastDateFormat.format(new Date()));
String stringFormattedDate = "2016-11-22T14:30:14+05:30";
System.out.println("String parsed into Date:");
System.out.println(fastDateFormat.parse(stringFormattedDate));
}
}
Here is the output of the code:
Date formatted into String:
2016-11-22T14:52:17+05:30
String parsed into Date:
Tue Nov 22 14:30:14 IST 2016
Note: The above code is of Apache Commons' lang3. The class org.apache.commons.lang.time.FastDateFormat does not support parsing, and it supports only formatting. For example, the output of the following code:
import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang.time.FastDateFormat;
public class DateFormatTest {
public static void main(String[] args) throws ParseException {
String stringDateFormat = "yyyy-MM-dd'T'HH:mm:ssZZ";
FastDateFormat fastDateFormat = FastDateFormat.getInstance(stringDateFormat);
System.out.println("Date formatted into String:");
System.out.println(fastDateFormat.format(new Date()));
String stringFormattedDate = "2016-11-22T14:30:14+05:30";
System.out.println("String parsed into Date:");
System.out.println(fastDateFormat.parseObject(stringFormattedDate));
}
}
will be this:
Date formatted into String:
2016-11-22T14:55:56+05:30
String parsed into Date:
Exception in thread "main" java.text.ParseException: Format.parseObject(String) failed
at java.text.Format.parseObject(Format.java:228)
at DateFormatTest.main(DateFormatTest.java:12)
If date string is like 2018-07-20T12:18:29.802Z
Use this
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

how to get a formatted date as milliseconds?

I have a formatted date from sqllite database, to use this in a graph view I need to format it in a long number.
The format is:
2012-07-11 10:55:21
how can I convert it to milliseconds?
You can convert the string into a Date object using this code:-
Date d = DateFormat.parse(String s)
And then convert it into milliseconds by using the inbuilt method
long millisec = d.getTime();
Use date.getTime()
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd, HH:mm:ss");
formatter.setLenient(false);
String oldTime = "2012-07-11 10:55:21";
Date oldDate = formatter.parse(oldTime);
long oldMillis = oldDate.getTime();
try this:
import java.util.*;
public class ConvertDateIntoMilliSecondsExample{
public static void main(String args[]){
//create a Date object
Date date = new Date();
System.out.println("Date is : " + date);
//use getTime() method to retrieve milliseconds
System.out.println("Milliseconds since January 1, 1970, 00:00:00 GMT : "
+ date.getTime());
}
}
java.time
Solution using java.time, the modern date-time API*:
import java.time.Instant;
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) {
// Test
System.out.println(toMillis("2012-07-11 10:55:21"));
}
public static long toMillis(String strDateTime) {
// Replace the parameter, ZoneId.systemDefault() which returns JVM's default
// timezone, as applicable e.g. to ZoneId.of("America/New_York")
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH)
.withZone(ZoneId.systemDefault());
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
Instant instant = zdt.toInstant();
return instant.toEpochMilli();
}
}
Output:
1342000521000
Learn more about the 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.

Timezone conversion for a specific datetime in java

I will be giving input date time for a timezone and the timezone for the input date time and we want the relevant DateTime in the expected timezone.
And here is my method.
convertToTimezone("03/08/2010 20:19:00 PM","Asia/Shanghai","US/Central");
The above time is the time in Asia/Shanghai. We would like to know what is the corresponding time in US/Central.
It's working fine but I am getting a 1-hour difference from the actual time.
Can I know where I am going wrong?
Here is the code:
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class DateUtil {
private static String format_date = "MM/dd/yyyy HH:mm:ss a";
public static void main(String a[]) {
try {
String sourceTimezone = "Asia/Shanghai";
String destTimezone = "US/Central";
String outputExpectedTimezone = convertToTimezone("03/08/2010 20:19:00 PM", sourceTimezone, destTimezone);
System.out.println("outputExpectedTimezone :" + outputExpectedTimezone);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static String convertToTimezone(String inputDate, String inputDateTimezone, String destinationDateTimezone)
throws Exception {
String outputDate = null;
SimpleDateFormat format = new SimpleDateFormat(format_date);
format.setTimeZone(TimeZone.getTimeZone(inputDateTimezone));
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(inputDateTimezone));
calendar.setTime(format.parse(inputDate));
calendar.add(Calendar.MILLISECOND, -(calendar.getTimeZone().getRawOffset()));
calendar.add(Calendar.MILLISECOND, -calendar.getTimeZone().getDSTSavings());
calendar.add(Calendar.MILLISECOND, TimeZone.getTimeZone(destinationDateTimezone).getRawOffset());
outputDate = format.format(calendar.getTime());
return outputDate;
}
}
You shouldn't be adding anything to the calendar - that represents a specific instant in time. In fact, you don't need a calendar at all.
Instead, have two different formats, one for each time zone:
public static String convertToTimezone(String inputDate,
String inputDateTimezone,
String destinationDateTimezone)
throws Exception
{
SimpleDateFormat parser = new SimpleDateFormat(format_date);
parser.setTimeZone(TimeZone.getTimeZone(inputDateTimezone));
Date date = parser.parse(inputDate);
SimpleDateFormat formatter = new SimpleDateFormat(format_date);
formatter.setTimeZone(TimeZone.getTimeZone(outputDateTimezone));
return formatter.format(date);
}
As an aside, I'd thoroughly recommend using Joda Time instead of the built-in date/time API.
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:
Since your input Date-Time does not have timezone information, parse it into a LocalDateTime
Attach the timezone of the input Date-Time with it to get a ZonedDateTime
Use the ZonedDateTime#withZoneSameInstant to convert this ZonedDateTime to the target ZonedDateTime
Return the formatted target ZonedDateTime.
Demo:
import java.time.LocalDateTime;
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) {
// Tests
System.out.println(convertToTimezone("03/08/2010 20:19:00 PM", "Asia/Shanghai", "US/Central"));
System.out.println(convertToTimezone("03/08/2010 20:19:00 PM", "Asia/Shanghai", "America/Mexico_City"));
}
static String convertToTimezone(String inputDate, String inputDateTimezone, String destinationDateTimezone) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm:ss a", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(inputDate, dtf);
ZonedDateTime zdtInput = ldt.atZone(ZoneId.of(inputDateTimezone));
ZonedDateTime zdtDestination = zdtInput.withZoneSameInstant(ZoneId.of(destinationDateTimezone));
return zdtDestination.format(dtf);
}
}
Output:
03/08/2010 06:19:00 AM
03/08/2010 06:19:00 AM
ONLINE DEMO
Note: Avoid using the deprecated ID, US/Central. Use the standard ID, America/Mexico_City where Mexico City is the largest city in this timezone.
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.

How to properly format the date?

The function shown below returns the date, e.g. "Sat Sep 8 00:00 PDT 2010". But I expected to get the date in the following format "yyyy-MM-dd HH:mm". What's wrong in this code?
String date = "2010-08-25";
String time = "00:00";
Also in one laptop the output for,e.g. 23:45 is 11:45. How can I define exactly the 24 format?
private static Date date(final String date,final String time) {
final Calendar calendar = Calendar.getInstance();
String[] ymd = date.split("-");
int year = Integer.parseInt(ymd[0]);
int month = Integer.parseInt(ymd[1]);
int day = Integer.parseInt(ymd[2]);
String[] hm = time.split(":");
int hour = Integer.parseInt(hm[0]);
int minute = Integer.parseInt(hm[1]);
calendar.set(Calendar.YEAR,year);
calendar.set(Calendar.MONTH,month);
calendar.set(Calendar.DAY_OF_MONTH,day);
calendar.set(Calendar.HOUR,hour);
calendar.set(Calendar.MINUTE,minute);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date d = calendar.getTime();
String dateString= dateFormat.format(d);
Date result = null;
try {
result = (Date)dateFormat.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
}
return result;
}
What's wrong in this code?
You seem to be expecting the returned Date object to know about the format you've parsed it from - it doesn't. It's just an instant in time. When you want a date in a particular format, you use SimpleDateFormat.format, it's as simple as that. (Well, or you use a better library such as Joda Time.)
Think of the Date value as being like an int - an int is just a number; you don't have "an int in hex" or "an int in decimal"... you make that decision when you want to format it. The same is true with Date.
(Likewise a Date isn't associated with a specific calendar, time zone or locale. It's just an instant in time.)
How did you print out the return result? If you simply use System.out.println(date("2010-08-25", "00:00") then you might get Sat Sep 8 00:00 PDT 2010 depending on your current date time format setting in your running machine. But well what you can do is:
Date d = date("2010-08-25", "00:00");
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm").format(d));
Just curious why do you bother with this whole process as you can simple get the result by concatenate your initial date and time string.
just use SimpleDateFormat class
See
date formatting java simpledateformat
The standard library does not support a formatted Date-Time object.
The function shown below returns the date, e.g. "Sat Sep 8 00:00 PDT
2010". But I expected to get the date in the following format
"yyyy-MM-dd HH:mm".
The standard Date-Time classes do not have any attribute to hold the formatting information. Even if some library or custom class promises to do so, it is breaking the Single Responsibility Principle. A Date-Time object is supposed to store the information about Date, Time, Timezone etc., not about the formatting. The only way to represent a Date-Time object in the desired format is by formatting it into a String using a Date-Time parsing/formatting type:
For the modern Date-Time API: java.time.format.DateTimeFormatter
For the legacy Date-Time API: java.text.SimpleDateFormat
About java.util.Date:
A java.util.Date object simply represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone e.g.
Date date = new Date(); // In your case, it will be Date date = date("2010-08-25", "00:00");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH);
// sdf.setTimeZone(TimeZone.getTimeZone("America/New_York")); // For a timezone-specific value
String strDate = sdf.format(date);
System.out.println(strDate);
Your function, Date date(String, String) is error-prone.
You can simply combine the date and time string with a separator and then use SimpleDateFormat to parse the combined string e.g. you can combine them with a whitespace character as the separator to use the same SimpleDateFormat shown above.
private static Date date(final String date, final String time) throws ParseException {
return sdf.parse(date + " " + time);
}
Note that using a separator is not a mandatory requirement e.g. you can do it as sdf.parse(date + time) but for this, you need to change the format of sdf to yyyy-MM-ddHH:mm which, although correct, may look confusing.
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH);
public static void main(String[] args) throws ParseException {
Date date = date("2010-08-25", "00:00");
String strDate = sdf.format(date);
System.out.println(strDate);
}
private static Date date(final String date, final String time) throws ParseException {
return sdf.parse(date + " " + time);
}
}
Output:
2010-08-25 00:00
ONLINE DEMO
Switch to java.time API.
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.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
LocalDateTime ldt = localDateTime("2010-08-25", "00:00");
// Default format i.e. the value of ldt.toString()
System.out.println(ldt);
// Custom format
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm", Locale.ENGLISH);
String strDate = dtf.format(ldt);
System.out.println(strDate);
}
private static LocalDateTime localDateTime(final String date, final String time) {
return LocalDateTime.of(LocalDate.parse(date), LocalTime.parse(time));
}
}
Output:
2010-08-25T00:00
2010-08-25 00:00
ONLINE DEMO
You must have noticed that I have not used DateTimeFormatter for parsing the String date and String time. It is because your date and time strings conform to the ISO 8601 standards. The modern Date-Time API is based on ISO 8601 and does not require using a DateTimeFormatter object explicitly as long as the Date-Time string conforms to the ISO 8601 standards.
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.
I'm surprise you are getting different date outputs on the different computers. In theory, SimpleDateFormat pattern "H" is supposed to output the date in a 24h format. Do you get 11:45pm or 11:45am?
Although it should not affect the result, SimpleDateFormat and Calendar are Locale dependent, so you can try to specify the exact locale that you want to use (Locale.US) and see if that makes any difference.
As a final suggestion, if you want, you can also try to use the Joda-Time library (DateTime) to do the date manipulation instead. It makes it significantly easier working with date objects.
DateTime date = new DateTime( 1991, 10, 13, 23, 39, 0);
String dateString = new SimpleDateFormat("yyyy-MM-dd HH:mm").format( date.toDate());
DateTime newDate = DateTime.parse( dateString, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"));

Categories