Calendar timezone , how does it work? - java

When I execute the below snippet
public static void main(String[] args) {
TimeZone timeZoneInd = TimeZone.getTimeZone("Asia/Calcutta");
TimeZone timeZoneAus = TimeZone.getTimeZone("Australia/Adelaide");
Calendar calendarInd = Calendar.getInstance(timeZoneInd);
Calendar calendarAus = Calendar.getInstance(timeZoneAus);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy-HH:mm:ss SSSS");
System.out.println("Australian time now :" + sdf.format(calendarAus.getTime()));
System.out.println("Indian time now :" + sdf.format(calendarInd.getTime()));
}
Why is it that both values are same ? Should'nt each print time corresponding to its timezone ?

That is because the time in each Calendar object is the same. If you want to format dates for different time zones, you will need to set the time zone in the format object, like this:
TimeZone timeZoneInd = TimeZone.getTimeZone("Asia/Calcutta");
TimeZone timeZoneAus = TimeZone.getTimeZone("Australia/Adelaide");
SimpleDateFormat formatInd = new SimpleDateFormat("dd/MM/yyyy-HH:mm:ss SSSS");
formatInd.setTimeZone(timeZoneInd);
SimpleDateFormat formatAus = new SimpleDateFormat("dd/MM/yyyy-HH:mm:ss SSSS");
formatAus.setTimeZone(timeZoneAus);
Calendar calendarInd = Calendar.getInstance(timeZoneInd);
Calendar calendarAus = Calendar.getInstance(timeZoneAus);
System.out.println("Australian time now :" + formatAus.format(new Date()));
System.out.println("Indian time now :" + formatInd.format(new Date()));
calendarAus.set(Calendar.HOUR_OF_DAY, 12);
calendarInd.set(Calendar.HOUR_OF_DAY, 12);
System.out.println("Australian time at noon :" + formatAus.format(calendarAus.getTime()));
System.out.println("Indian time at noon :" + formatInd.format(calendarInd.getTime()));
This for me gives the following output:
Australian time now :20/02/2015-23:00:51 0081
Indian time now :20/02/2015-18:00:51 0082
Australian time at noon :20/02/2015-12:00:51 0081
Indian time at noon :20/02/2015-12:00:51 0081
You should use the SimpleDateFormat for formatting your dates, the Calendar object should be used for manipulating dates.

Related

How do I convert date/time from one timezone to another? [duplicate]

i have written this code to convert the current system date and time to some other timezone. I am not getting any error but i am not getting my output as expected. Like if i execute my program at a particular time.. My output is ::
The current time in India is :: Fri Feb 24 16:09:23 IST 2012
The date and time in :: Central Standard Time is :: Sat Feb 25 03:39:23 IST 2012
And the actual Time according to CST time zone is ::
Friday, 24 February 4:39:16 a.m(GMT - 6:00)
So there's some time gap. and i don't know why this is happening. Any help will be appreciated.. The code is ::
package MyPackage;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Temp2 {
public static void main(String[] args) {
try {
Calendar currentdate = Calendar.getInstance();
String strdate = null;
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
strdate = formatter.format(currentdate.getTime());
TimeZone obj = TimeZone.getTimeZone("CST");
formatter.setTimeZone(obj);
//System.out.println(strdate);
//System.out.println(formatter.parse(strdate));
Date theResult = formatter.parse(strdate);
System.out.println("The current time in India is :: " +currentdate.getTime());
System.out.println("The date and time in :: "+ obj.getDisplayName() + "is ::" + theResult);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
It's over the web. Could have googled. Anyways, here is a version for you (shamelessly picked and modified from here):
Calendar calendar = Calendar.getInstance();
TimeZone fromTimeZone = calendar.getTimeZone();
TimeZone toTimeZone = TimeZone.getTimeZone("CST");
calendar.setTimeZone(fromTimeZone);
calendar.add(Calendar.MILLISECOND, fromTimeZone.getRawOffset() * -1);
if (fromTimeZone.inDaylightTime(calendar.getTime())) {
calendar.add(Calendar.MILLISECOND, calendar.getTimeZone().getDSTSavings() * -1);
}
calendar.add(Calendar.MILLISECOND, toTimeZone.getRawOffset());
if (toTimeZone.inDaylightTime(calendar.getTime())) {
calendar.add(Calendar.MILLISECOND, toTimeZone.getDSTSavings());
}
System.out.println(calendar.getTime());
Your mistake is to call parse instead of format.
You call parse to parse a Date from a String, but in your case you've got a Date and need to format it using the correct Timezone.
Replace your code with
Calendar currentdate = Calendar.getInstance();
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
TimeZone obj = TimeZone.getTimeZone("CST");
formatter.setTimeZone(obj);
System.out.println("Local:: " +currentdate.getTime());
System.out.println("CST:: "+ formatter.format(currentdate.getTime()));
and I hope you'll get the output you are expecting.
SimpleDateFormat#setTimezone() is the answer. One formatter with ETC timezone you use for parsing, another with UTC for producing output string:
DateFormat dfNy = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT);
dfNy.setTimeZone(TimeZone.getTimeZone("EST"));
DateFormat dfUtc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT);
dfUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
return dfUtc.format(dfNy.parse(input));
} catch (ParseException e) {
return null; // invalid input
}
Handling dates in Java in my daily work is a non-trivial task. I suggest you to use Joda-Time that simplify our coding days and you don't have to "re-invent the wheel".
You can use two SimpleDateFormat, one for parse the date string with EST timezone, one for print the date with UTC timezone
String format = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat estFormatter = new SimpleDateFormat(format);
estFormatter.setTimeZone(TimeZone.getTimeZone("EST"));
Date date = estFormatter.parse("2015-11-01 01:00:00");
SimpleDateFormat utcFormatter = new SimpleDateFormat(format);
utcFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(utcFormatter.format(date));
You can just use "CST6CDT"
because in some countries they follow CDT in summer and CST in winter
public static String getDateInCST() {
Calendar calendar = Calendar.getInstance();
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone( "CST6CDT"));
String strdate = formatter.format(calendar.getTime());
TimeZone.getAvailableIDs();
return strdate;
}
Problem is when you print date obj it call toString method and it will print in your machines default time zone. Try this code and see difference.
Calendar currentdate = Calendar.getInstance();
String strdate = null;
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ssz");
strdate = formatter.format(currentdate.getTime());
System.out.println("strdate=>" + strdate);
TimeZone obj = TimeZone.getTimeZone("CST");
formatter.setTimeZone(obj);
strdate = formatter.format(currentdate.getTime());
Date theResult = formatter.parse(strdate);
System.out.println("The current time in India is :: " +currentdate.getTime());
System.out.println("The date and time in :: " + obj.getDisplayName() + "is ::" + theResult);
System.out.println("The date and time in :: " + obj.getDisplayName() + "is ::" + strdate);
First message, don’t handle your date and time as strings in your code. Just as you don’t handle numbers and Boolean values as strings (I hope). Use proper date-time objects.
java.time
Sometimes we get date and time as string input. It may be from a text file, from the user or from data exchange with another system, for example. In those cases parse into a proper date-time object first thing. Second message, use java.time, the modern Java date and time API, for your date and time work.
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
String input = "2015-11-01 01:00:00";
ZonedDateTime nyTime = LocalDateTime.parse(input, formatter)
.atZone(ZoneId.of("America/New_York"));
System.out.println("Time in New York: " + nyTime);
Output from this snippet is:
Time in New York: 2015-11-01T01:00-04:00[America/New_York]
To convert to GMT:
OffsetDateTime gmtTime = nyTime.toOffsetDateTime()
.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println("GMT Time: " + gmtTime);
GMT Time: 2015-11-01T05:00Z
If you need to give string output, format using a date-time formatter. Here’s an example of formatting for an American audience:
DateTimeFormatter userFormatter
= DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
.withLocale(Locale.US);
String formattedDateTime = gmtTime.format(userFormatter);
System.out.println("GMT Time formatted for user: " + formattedDateTime);
GMT Time formatted for user: Nov 1, 2015, 5:00:00 AM
You additionally asked:
Between the two results below, which one should you take?
I understand that you ask because both are valid answers. On November 1, 2015 summer time (DST) ended at 2 AM. That is, after 01:59:59 came 01:00:00 a second time. So when we have got 2015-11-01 01:00:00 as input, it is ambiguous. It could be in Eastern Daylight Time, equal to 05:00 GMT, or it could be in Eastern Standard Time, one hour later, hence equal to 06:00 GMT. There is no way that I can tell you which of them is correct in your case. You may control which result you get using withEarlierOffsetAtOverlap() or withLaterOffsetAtOverlap(). Above we got the DST interpretation. So to get the standard time interpretation:
nyTime = nyTime.withLaterOffsetAtOverlap();
System.out.println("Alternate time in New York: " + nyTime);
Alternate time in New York: 2015-11-01T01:00-05:00[America/New_York]
We notice that the hour of day is still 01:00, but the offset is now -05:00 instead of -04:00. This also gives us a different GMT time:
GMT Time: 2015-11-01T06:00Z
GMT Time formatted for user: Nov 1, 2015, 6:00:00 AM
Avoid SimpleDateFormat and friends
While the other answers are generally correct, the classes DateFormat, SimpleDateFormat, Date and Calendar used there are poorly designed and long outdated. The first two are particularly troublesome. I recommend you avoid all of them. I frankly find the modern API so much nicer to work with.
Link
Oracle tutorial: Date Time explaining how to use java.time.
Please refer to below mentioned code.
DateFormat utcConverter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
utcConverter.setTimeZone(TimeZone.getTimeZone("GMT"));
String sampleDateTime = "2015-11-01 01:00:00";
DateFormat nyConverter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
nyConverter.setTimeZone(TimeZone.getTimeZone("EST"));
Calendar nyCal = Calendar.getInstance();
nyCal.setTime(nyConverter.parse(sampleDateTime));
System.out.println("NY TIME :" +nyConverter.format(nyCal.getTime()));
System.out.println("GMT TIME :" +utcConverter.format(nyCal.getTime()));
2020 Answer Here
If you want the new java.time.* feature but still want to mess with java.util.Date:
public static Date convertBetweenTwoTimeZone(Date date, String fromTimeZone, String toTimeZone) {
ZoneId fromTimeZoneId = ZoneId.of(fromTimeZone);
ZoneId toTimeZoneId = ZoneId.of(toTimeZone);
ZonedDateTime fromZonedDateTime =
ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).withZoneSameLocal(fromTimeZoneId);
ZonedDateTime toZonedDateTime = fromZonedDateTime
.withZoneSameInstant(toTimeZoneId)
.withZoneSameLocal(ZoneId.systemDefault())
;
return Date.from(toZonedDateTime.toInstant());
}
for java.sql.Timestamp
public static Timestamp convertBetweenTwoTimeZone(Timestamp timestamp, String fromTimeZone, String toTimeZone) {
ZoneId fromTimeZoneId = ZoneId.of(fromTimeZone);
ZoneId toTimeZoneId = ZoneId.of(toTimeZone);
LocalDateTime localDateTimeBeforeDST = timestamp.toLocalDateTime();
ZonedDateTime fromZonedDateTime = ZonedDateTime.of(localDateTimeBeforeDST, fromTimeZoneId);
ZonedDateTime toZonedDateTime = fromZonedDateTime.withZoneSameInstant(toTimeZoneId);
return Timestamp.valueOf(toZonedDateTime.toLocalDateTime());
}
For google calendar API
private String getFormatedDate(Date date)
{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss+05:30");
df.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
return df.format(date);
}

Daylight savings time being added when string is converted to Timestamp in Java

My application receives timestamp in string format and we used parse() method in SimpleDateFormat class to convert that String to Timestamp object. My application is running in America/New_York timezone, so we faced daylight savings time issue for timestamps between March 9th 2.00 to 2.59 am. We fixed this issue by modifying default timezone properties to make sure all the daylight savings fields are reset to zero. But when we created current timestamp object using java.util.Date class after daylight savings has been changed (March 22), it showed up as 1 hour less than the actual current timestamp. This is because of changing the properties of default timezone.
public class DateTest {
static TimeZone defaultTimeZone = TimeZone.getDefault();
Timestamp timestamp1;
public static void main(String[] args) throws Exception {
DateTest dateTest = new DateTest();
System.out.println("Current date before changing Timezone:" + new java.util.Date());
//Adds one hour extra to the actual timestamp
System.out.println("Converted Timestamp with Daylight:" + convertStringToTimestamp("2014030902101900"));
System.out.println("=====================================================================");
//Displays as the actual timestamp
dateTest.setTimestamp1(convertStringToTimestampWithoutDaylight("2014030902101900"));
System.out.println("Converted Timestamp with Daylight savings:" + dateTest.getTimestamp1());
//1 hour is reduced compared to current timestamp as Daylight savings time is removed
System.out.println("Current date after changing Timezone:" + new java.util.Date());
System.out.println("=====================================================================");
//Reset back to the original timezone
TimeZone.setDefault(defaultTimeZone);
Displays current timestamp
System.out.println("Current date after Timezone reset:" + new java.util.Date());
//Adds one hour again
System.out.println("Converted Timestamp after Timezone reset:" + dateTest.getTimestamp1());
System.out.println("=====================================================================");
}
}
We are using both current timestamp object and the string to timestamp conversion in our project. I tried with Joda-Time also, but at the end we need Timestamp object when Joda-Time is converted to Timestamp, daylight savings time is being added.
DateTime dateTime = DateTime.now();
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateTime.toDate());
System.out.println("Current Timestamp:" + new Timestamp(calendar.getTimeInMillis()));
LocalDateTime localdateTime = LocalDateTime.parse("2014030902101100", DateTimeFormat.forPattern("yyyyMMddHHmmssSS"));
Calendar calendar2 = Calendar.getInstance();
calendar2.setTime(localdateTime.toDate());
System.out.println("Converted Timestamp:" + new Timestamp(calendar2.getTimeInMillis()));
Output:
Current Timestamp:2014-03-22 09:15:09.478
Converted Timestamp:2014-03-09 03:10:11.0
In your parallel thread on LinkedIn you stated that you do not know what time zone your timestamps corresponds to. In most cases this is bad. But if this is indeed the situation you are in, you are free to treat them as timestamps in any timezone you choose. If you don't know whether the timezone to which your timestamps correspond has daylight savings and if does, what rules they follow, your safest choice is to consider them belonging to a time zone that doesn't have daylight savings. I would suggest using UTC. So, before parsing or formating a timestamp you need to set the timezone of the SimpleDateFormat to UTC:
public static void main(String[] args) throws Exception {
Date date = parseTimestamp("2014030902101100");
System.out.println("Parsed date: " + formatDate(date));
date = parseTimestamp("2014032202101100");
System.out.println("Parsed date: " + formatDate(date));
}
private static Date parseTimestamp(String timestamp) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = sdf.parse(timestamp);
return date;
}
private static String formatDate(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS z");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
return sdf.format(date);
}
The output is:
Parsed date: 2014-03-09 02:10:11.00 UTC
Parsed date: 2014-03-22 02:10:11.00 UTC
You can try to parse the string with SimpleDateFormat,
something like
SimpleDateFormat sd = new SimpleDateFormat("yyyyMMddHHmmssSSz");
Date date = sd.parse("2014030902101100GMT-05:00");
and for the z (timezone) parameter you could add GMT-05:00 (New York offset from GMT/UTC) to the timestamp string that you have at hand.
After this you can convert to what ever you would like.
simpledateforamt.parse will give you date (java.util.date).
Convesion from date to Timestamp is straight forward.
long ms = date.getTime();
Timestamp t = new Timestamp(ms);
DateTime dateTime = DateTime.now();
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateTime.toDate());
System.out.println("Current Timestamp:" + new Timestamp(calendar.getTimeInMillis()));
LocalDateTime localdateTime = LocalDateTime.parse("2014030902101100",
DateTimeFormat.forPattern("yyyyMMddHHmmssSS"));
System.out.println("Converted Timestamp:" + Timestamp.valueOf(localdateTime.toString("yyyy-mm-dd hh:mm:ss")));

Date and time conversion to some other Timezone in java

i have written this code to convert the current system date and time to some other timezone. I am not getting any error but i am not getting my output as expected. Like if i execute my program at a particular time.. My output is ::
The current time in India is :: Fri Feb 24 16:09:23 IST 2012
The date and time in :: Central Standard Time is :: Sat Feb 25 03:39:23 IST 2012
And the actual Time according to CST time zone is ::
Friday, 24 February 4:39:16 a.m(GMT - 6:00)
So there's some time gap. and i don't know why this is happening. Any help will be appreciated.. The code is ::
package MyPackage;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Temp2 {
public static void main(String[] args) {
try {
Calendar currentdate = Calendar.getInstance();
String strdate = null;
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
strdate = formatter.format(currentdate.getTime());
TimeZone obj = TimeZone.getTimeZone("CST");
formatter.setTimeZone(obj);
//System.out.println(strdate);
//System.out.println(formatter.parse(strdate));
Date theResult = formatter.parse(strdate);
System.out.println("The current time in India is :: " +currentdate.getTime());
System.out.println("The date and time in :: "+ obj.getDisplayName() + "is ::" + theResult);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
It's over the web. Could have googled. Anyways, here is a version for you (shamelessly picked and modified from here):
Calendar calendar = Calendar.getInstance();
TimeZone fromTimeZone = calendar.getTimeZone();
TimeZone toTimeZone = TimeZone.getTimeZone("CST");
calendar.setTimeZone(fromTimeZone);
calendar.add(Calendar.MILLISECOND, fromTimeZone.getRawOffset() * -1);
if (fromTimeZone.inDaylightTime(calendar.getTime())) {
calendar.add(Calendar.MILLISECOND, calendar.getTimeZone().getDSTSavings() * -1);
}
calendar.add(Calendar.MILLISECOND, toTimeZone.getRawOffset());
if (toTimeZone.inDaylightTime(calendar.getTime())) {
calendar.add(Calendar.MILLISECOND, toTimeZone.getDSTSavings());
}
System.out.println(calendar.getTime());
Your mistake is to call parse instead of format.
You call parse to parse a Date from a String, but in your case you've got a Date and need to format it using the correct Timezone.
Replace your code with
Calendar currentdate = Calendar.getInstance();
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
TimeZone obj = TimeZone.getTimeZone("CST");
formatter.setTimeZone(obj);
System.out.println("Local:: " +currentdate.getTime());
System.out.println("CST:: "+ formatter.format(currentdate.getTime()));
and I hope you'll get the output you are expecting.
SimpleDateFormat#setTimezone() is the answer. One formatter with ETC timezone you use for parsing, another with UTC for producing output string:
DateFormat dfNy = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT);
dfNy.setTimeZone(TimeZone.getTimeZone("EST"));
DateFormat dfUtc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT);
dfUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
return dfUtc.format(dfNy.parse(input));
} catch (ParseException e) {
return null; // invalid input
}
Handling dates in Java in my daily work is a non-trivial task. I suggest you to use Joda-Time that simplify our coding days and you don't have to "re-invent the wheel".
You can use two SimpleDateFormat, one for parse the date string with EST timezone, one for print the date with UTC timezone
String format = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat estFormatter = new SimpleDateFormat(format);
estFormatter.setTimeZone(TimeZone.getTimeZone("EST"));
Date date = estFormatter.parse("2015-11-01 01:00:00");
SimpleDateFormat utcFormatter = new SimpleDateFormat(format);
utcFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(utcFormatter.format(date));
You can just use "CST6CDT"
because in some countries they follow CDT in summer and CST in winter
public static String getDateInCST() {
Calendar calendar = Calendar.getInstance();
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone( "CST6CDT"));
String strdate = formatter.format(calendar.getTime());
TimeZone.getAvailableIDs();
return strdate;
}
Problem is when you print date obj it call toString method and it will print in your machines default time zone. Try this code and see difference.
Calendar currentdate = Calendar.getInstance();
String strdate = null;
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ssz");
strdate = formatter.format(currentdate.getTime());
System.out.println("strdate=>" + strdate);
TimeZone obj = TimeZone.getTimeZone("CST");
formatter.setTimeZone(obj);
strdate = formatter.format(currentdate.getTime());
Date theResult = formatter.parse(strdate);
System.out.println("The current time in India is :: " +currentdate.getTime());
System.out.println("The date and time in :: " + obj.getDisplayName() + "is ::" + theResult);
System.out.println("The date and time in :: " + obj.getDisplayName() + "is ::" + strdate);
First message, don’t handle your date and time as strings in your code. Just as you don’t handle numbers and Boolean values as strings (I hope). Use proper date-time objects.
java.time
Sometimes we get date and time as string input. It may be from a text file, from the user or from data exchange with another system, for example. In those cases parse into a proper date-time object first thing. Second message, use java.time, the modern Java date and time API, for your date and time work.
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
String input = "2015-11-01 01:00:00";
ZonedDateTime nyTime = LocalDateTime.parse(input, formatter)
.atZone(ZoneId.of("America/New_York"));
System.out.println("Time in New York: " + nyTime);
Output from this snippet is:
Time in New York: 2015-11-01T01:00-04:00[America/New_York]
To convert to GMT:
OffsetDateTime gmtTime = nyTime.toOffsetDateTime()
.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println("GMT Time: " + gmtTime);
GMT Time: 2015-11-01T05:00Z
If you need to give string output, format using a date-time formatter. Here’s an example of formatting for an American audience:
DateTimeFormatter userFormatter
= DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
.withLocale(Locale.US);
String formattedDateTime = gmtTime.format(userFormatter);
System.out.println("GMT Time formatted for user: " + formattedDateTime);
GMT Time formatted for user: Nov 1, 2015, 5:00:00 AM
You additionally asked:
Between the two results below, which one should you take?
I understand that you ask because both are valid answers. On November 1, 2015 summer time (DST) ended at 2 AM. That is, after 01:59:59 came 01:00:00 a second time. So when we have got 2015-11-01 01:00:00 as input, it is ambiguous. It could be in Eastern Daylight Time, equal to 05:00 GMT, or it could be in Eastern Standard Time, one hour later, hence equal to 06:00 GMT. There is no way that I can tell you which of them is correct in your case. You may control which result you get using withEarlierOffsetAtOverlap() or withLaterOffsetAtOverlap(). Above we got the DST interpretation. So to get the standard time interpretation:
nyTime = nyTime.withLaterOffsetAtOverlap();
System.out.println("Alternate time in New York: " + nyTime);
Alternate time in New York: 2015-11-01T01:00-05:00[America/New_York]
We notice that the hour of day is still 01:00, but the offset is now -05:00 instead of -04:00. This also gives us a different GMT time:
GMT Time: 2015-11-01T06:00Z
GMT Time formatted for user: Nov 1, 2015, 6:00:00 AM
Avoid SimpleDateFormat and friends
While the other answers are generally correct, the classes DateFormat, SimpleDateFormat, Date and Calendar used there are poorly designed and long outdated. The first two are particularly troublesome. I recommend you avoid all of them. I frankly find the modern API so much nicer to work with.
Link
Oracle tutorial: Date Time explaining how to use java.time.
Please refer to below mentioned code.
DateFormat utcConverter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
utcConverter.setTimeZone(TimeZone.getTimeZone("GMT"));
String sampleDateTime = "2015-11-01 01:00:00";
DateFormat nyConverter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
nyConverter.setTimeZone(TimeZone.getTimeZone("EST"));
Calendar nyCal = Calendar.getInstance();
nyCal.setTime(nyConverter.parse(sampleDateTime));
System.out.println("NY TIME :" +nyConverter.format(nyCal.getTime()));
System.out.println("GMT TIME :" +utcConverter.format(nyCal.getTime()));
2020 Answer Here
If you want the new java.time.* feature but still want to mess with java.util.Date:
public static Date convertBetweenTwoTimeZone(Date date, String fromTimeZone, String toTimeZone) {
ZoneId fromTimeZoneId = ZoneId.of(fromTimeZone);
ZoneId toTimeZoneId = ZoneId.of(toTimeZone);
ZonedDateTime fromZonedDateTime =
ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).withZoneSameLocal(fromTimeZoneId);
ZonedDateTime toZonedDateTime = fromZonedDateTime
.withZoneSameInstant(toTimeZoneId)
.withZoneSameLocal(ZoneId.systemDefault())
;
return Date.from(toZonedDateTime.toInstant());
}
for java.sql.Timestamp
public static Timestamp convertBetweenTwoTimeZone(Timestamp timestamp, String fromTimeZone, String toTimeZone) {
ZoneId fromTimeZoneId = ZoneId.of(fromTimeZone);
ZoneId toTimeZoneId = ZoneId.of(toTimeZone);
LocalDateTime localDateTimeBeforeDST = timestamp.toLocalDateTime();
ZonedDateTime fromZonedDateTime = ZonedDateTime.of(localDateTimeBeforeDST, fromTimeZoneId);
ZonedDateTime toZonedDateTime = fromZonedDateTime.withZoneSameInstant(toTimeZoneId);
return Timestamp.valueOf(toZonedDateTime.toLocalDateTime());
}
For google calendar API
private String getFormatedDate(Date date)
{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss+05:30");
df.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
return df.format(date);
}

Adding days with java.util.Calendar gives strange results

Using java.util.Calendar to add a single day to a Date, and SimpleDateFormat to display the result, sometimes seems to lose a day (generally in March) and sometimes skips a day (in November).
The program below, with output, illustrates the issue. Notice that I'm just adding one day at a time, then skipping a few months and adding a few more days. You'll see that 2008-03-09 gets printed twice, but 2008-11-02 is skipped. The same thing happens in other years, but on different days. I had to experiment to find the days that cause the problem.
If I don't set the timezone to UTC in the SimpleDateFormat then the problem does not occur. I ran this on a machine in the US Central Time Zone.
This certainly looks like a bug in Calendar or SimpleDateFormat, but I have not been able to find it documented anywhere. Anybody have an explanation of what is happening here?
The program:
package mab;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class CalendarHiccup2 {
public static void main(String[] args) {
addDays("2008-03-08");
addDays("2009-03-07");
addDays("2010-03-13");
}
public static void addDays(String dateString) {
System.out.println("Got dateString: " + dateString);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Calendar calendar = Calendar.getInstance();
try {
calendar.setTime(sdf.parse(dateString));
Date day1 = calendar.getTime();
System.out.println(" day1 = " + sdf.format(day1));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day2 = calendar.getTime();
System.out.println(" day2 = " + sdf.format(day2));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day3 = calendar.getTime();
System.out.println(" day3 = " + sdf.format(day3));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day4 = calendar.getTime();
System.out.println(" day4 = " + sdf.format(day4));
// Skipping a few days ahead:
calendar.add(java.util.Calendar.DAY_OF_MONTH, 235);
Date day5 = calendar.getTime();
System.out.println(" day5 = " + sdf.format(day5));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day6 = calendar.getTime();
System.out.println(" day6 = " + sdf.format(day6));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day7 = calendar.getTime();
System.out.println(" day7 = " + sdf.format(day7));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day8 = calendar.getTime();
System.out.println(" day8 = " + sdf.format(day8));
} catch (Exception e) {
}
}
}
The output:
Got dateString: 2008-03-08
day1 = 2008-03-08
day2 = 2008-03-09
day3 = 2008-03-09
day4 = 2008-03-10
day5 = 2008-10-31
day6 = 2008-11-01
day7 = 2008-11-03
day8 = 2008-11-04
Got dateString: 2009-03-07
day1 = 2009-03-07
day2 = 2009-03-08
day3 = 2009-03-08
day4 = 2009-03-09
day5 = 2009-10-30
day6 = 2009-10-31
day7 = 2009-11-02
day8 = 2009-11-03
Got dateString: 2010-03-13
day1 = 2010-03-13
day2 = 2010-03-14
day3 = 2010-03-14
day4 = 2010-03-15
day5 = 2010-11-05
day6 = 2010-11-06
day7 = 2010-11-08
day8 = 2010-11-09
This is caused by the daylight saving time and is completely correct.
The time (on north hemisphere) is advanced one hour typically in March and moved back in November.
It looks more like a day light saving time issue, which changes in Mar and Nov. Can you try setting the time element to 00:00:00? If you do,
addDays("2008-03-08 00:00:00");
addDays("2009-03-07 00:00:00");
addDays("2010-03-13 00:00:00");
and change the format to,
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
you'll see the difference it makes in the time elements.
When you have these kind of issues you have to print the Calendar and Date instances to figure out what's going on.
The following:
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
changes the time of your Calendar depending on your JVM local time (and timezone). Calendar.getInstance(); creates a Calendar in your JVM local time, when you do calendar.setTime(sdf.parse(".....")) that sets the time in UTC (given how you created the sdf!). Depending on the DoY (and the Year as well!) that can make you pass the midnight and when you print your Date with the yyyy-MM-dd format you see the one day difference.
Print the full Calendar and full Date and you'll figure out what's going on!
Daylight Saving Time
The answer by Tomasz Nurkiewicz is correct, the problem is Daylight Saving Time (DST).
the local time changes at 02:00 local standard time to 03:00 local daylight time on the second Sunday in March and returns at 02:00 local daylight time to 01:00 local standard time on the first Sunday in November.
See Wikipedia on Central Time Zone
Joda-Time
The Joda-Time library makes this kind of work much easier.
A DateTime in Joda-Time knows its own time zone. To use UTC/GMT (no time offset), pass the built-in constant DateTimeZone.UTC.
To print out only the date portion of a date-time, use a DateTimeFormatter.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
String dateString = "2008-03-08";
// withTimeAtStartOfDay() is probably superfluous in this example, but I like that it self-documents our focus on the day rather than a particular time of day.
DateTime dateTime = new DateTime( dateString, DateTimeZone.UTC ).withTimeAtStartOfDay();
DateTime dateTimePlus1 = dateTime.plusDays( 1 ).withTimeAtStartOfDay();
DateTime dateTimePlus2 = dateTime.plusDays( 2 ).withTimeAtStartOfDay();
DateTime dateTimePlus3 = dateTime.plusDays( 3 ).withTimeAtStartOfDay();
Dump to console…
System.out.println("dateTime: " + dateTime );
System.out.println("dateTime (date portion): " + ISODateTimeFormat.date().withZone( DateTimeZone.UTC ).print( dateTime ) );
System.out.println("dateTimePlus1: " + dateTimePlus1 );
System.out.println("dateTimePlus2: " + dateTimePlus2 );
System.out.println("dateTimePlus3: " + dateTimePlus3 );
When run…
dateTime: 2008-03-08T00:00:00.000Z
dateTime (date portion): 2008-03-08
dateTimePlus1: 2008-03-09T00:00:00.000Z
dateTimePlus2: 2008-03-10T00:00:00.000Z
dateTimePlus3: 2008-03-11T00:00:00.000Z

Unexpected results when subtracting dates

Here is the code, for your viewing pleasure:
public static void main(String[] args) throws Exception {
Calendar cal = Calendar.getInstance();
cal.set(2010, Calendar.JULY, 10, 1, 0, 20);
Date d1 = cal.getTime();
Date d2 = new Date();
int seconds = 22;
d2.setTime(d1.getTime() - seconds*1000);
SimpleDateFormat iso_format = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss");
System.out.println(iso_format.format(d1) + " - " + seconds + "s = " + iso_format.format(d2));
}
Output: 2010-07-10 01:00:20 - 22s = 2010-07-10 24:59:58
Shouldn't the answer be 2010-07-09 24:59:58? Why does it loop back to the same day? Is there a way to fix it?
the hour 24 (since you used 'kk' to format) is considered the next day, ie the 10th. it is equivalent to midnight. I use 'HH' to format hours, which would display the 24th hour as '00'. this makes more sense to me and i believe is more standards compliant.
the date changes over at the 00/24th hour. if you were to subtract another hour from the resulting date, the date would become the 9th as expected.
also, if you want true ISO time format 'HH' is better than 'kk'.
http://en.wikipedia.org/wiki/ISO_8601#Times

Categories