I want to convert a String 24 May 2020 07:40 AM to date format Mon May 24 07:40:55 IST 2020. I tried using Calendar and SimpleDateFormatter but didn't find a solution. Any help is appreciated.
I want the return type to be Date since I have to compare it with a couple of Dates.
java.time
When you’ve got some Date objects — likely from a legacy API that you cannot afford to upgrade to java.time just now — I still recommend that you use java.time, the modern Java date and time API, for your comparisons.
In the following example I am using Instant from java.time, but you may use ZonedDateTime or some other modern type too.
DateTimeFormatter fromFormatter = DateTimeFormatter.ofPattern("d MMM uuuu hh:mm a", Locale.ENGLISH);
Date anOldfashionedDate = new Date(1_590_286_000_000L);
Date anotherOldfashionedDate = new Date(1_590_287_000_000L);
System.out.println("The Date objects are " + anOldfashionedDate + " and " + anotherOldfashionedDate);
String aString = "24 May 2020 07:40 AM";
Instant instantFromDate = anOldfashionedDate.toInstant();
Instant instantFromAnotherDate = anotherOldfashionedDate.toInstant();
Instant instantFromString = LocalDateTime.parse(aString, fromFormatter)
.atZone(ZoneId.of("Asia/Kolkata"))
.toInstant();
System.out.println("Comparing " + instantFromDate + " and " + instantFromString + ": "
+ instantFromDate.compareTo(instantFromString));
System.out.println("Comparing " + instantFromAnotherDate + " and " + instantFromString + ": "
+ instantFromAnotherDate.compareTo(instantFromString));
Output is (when running in Asia/Kolkata time zone):
The Date objects are Sun May 24 07:36:40 IST 2020 and Sun May 24 07:53:20 IST 2020
Comparing 2020-05-24T02:06:40Z and 2020-05-24T02:10:00Z: -1
Comparing 2020-05-24T02:23:20Z and 2020-05-24T02:10:00Z: 1
An Instant prints in UTC; this is what its toString method generates. The trailing Z means UTC. Since India Standard Time is 5 hours 30 minutes ahead of UTC, 07:40 AM in India is the same time as 02:10 in UTC.
Given that you embark on using java.time now, you are well prepared when one day your legacy API gets upgraded to using java.time too.
The opposite conversion
If you do insist on using Date, to answer your question as asked, the opposite conversion is easy too:
Date oldfashionedDateFromInstantFromString = Date.from(instantFromString);
System.out.println("Converting to old-fashioned: " + oldfashionedDateFromInstantFromString);
Converting to old-fashioned: Sun May 24 07:40:00 IST 2020
Link
Oracle tutorial: Date Time explaining how to use java.time.
Related
I just wanted to get offset(+02:00) from TimeZone but seems like it is not working for IST, JST, EST, and BET.
TimeZone exchangeTimeZone = banker.getTimeZone();
String timeZone = ZonedDateTime.now(ZoneId.of(exchangeTimeZone.getID())).getOffset().getId();
It is returning error "Unknown time-zone ID: EST". Date object is not avilable with me.
Use ZoneId.SHORT_IDS
ZonedDateTime.now(ZoneId.of(exchangeTimeZone.getID(), ZoneId.SHORT_IDS))
.getOffset().getId();
TimeZone.toZoneId()
// Never do this in your code: Get a TimeZone with ID EST for demonstration only.
TimeZone tz = TimeZone.getTimeZone("EST");
String currentOffsetString = ZonedDateTime.now(tz.toZoneId())
.getOffset()
.getId();
System.out.println(currentOffsetString);
Output when running just now:
-05:00
Contrary to the one-arg ZoneId.of method that you used in your code, TimeZone.toZoneId() does handle the deprecated three letter abbreviations (which may be considered an advantage or a disadvantage depending on your situation and your taste). So the above code works with many such three letter abbreviations too, including EST.
I am only hesitatingly including the first code line above. There are several things wrong with it: We should not create old-fashioned TimeZone objects in our code but rely on the modern ZonedId and related classes from java.time, the modern Java date and time API. We should not rely on three letter time zone abbreviations either. They are deprecated, not standardized and typically ambiguous. EST, for example, may mean Australian Eastern Standard Time or North American Eastern Standard Time. To increase confusion some will expect you to get Eastern Time with summer time (DST) in summer. With TimeZone you don’t. You get a time zone that uses standard time all year. The same is not true for AST, PST nor CST.
However you often cannot control what you get from an API. And if you’re unlucky enough to get an old-fashioned TimeZone object with ID EST, the above code shows you the conversion you need to get into the realm of java.time.
You could try to find a mapping for an abbreviation you got:
public static ZoneId getFromAbbreviation(String abbreviation) {
return ZoneId.of(ZoneId.SHORT_IDS.get(abbreviation));
}
You could get the offsets like in this main:
public static void main(String[] args) {
ZoneId istEquivalent = getFromAbbreviation("IST");
ZoneId estEquivalent = getFromAbbreviation("EST");
ZoneId jstEquivalent = getFromAbbreviation("JST");
ZoneId betEquivalent = getFromAbbreviation("BET");
ZonedDateTime istNow = ZonedDateTime.now(istEquivalent);
ZonedDateTime estNow = ZonedDateTime.now(estEquivalent);
ZonedDateTime jstNow = ZonedDateTime.now(jstEquivalent);
ZonedDateTime betNow = ZonedDateTime.now(betEquivalent);
System.out.println("IST --> " + istEquivalent + " with offset " + istNow.getOffset());
System.out.println("EST --> " + estEquivalent + " with offset " + estNow.getOffset());
System.out.println("JST --> " + jstEquivalent + " with offset " + jstNow.getOffset());
System.out.println("BET --> " + betEquivalent + " with offset " + betNow.getOffset());
}
the output is
IST --> Asia/Kolkata with offset +05:30
EST --> -05:00 with offset -05:00
JST --> Asia/Tokyo with offset +09:00
BET --> America/Sao_Paulo with offset -03:00
As you can see, EST simply doesn't have a zone name, just an offset.
I have a query for an Oracle database that returns a datetime column. In the java method, the column is converted to a string.
A portion of the code looks like this:
ResultSet rs;
HashMap<String, String> hm=new HashMap<String, String> ();
hm.put("SchEndDate2", rs1.getString("END_DT_TM_GMT"));
When I view the strings value in the debugger it looks like this: "2019-07-04 11:00:00.0"
I need to convert this string to the datetime format of this: "yyyy-MM-dd'T'HH:mm"
I tried this SimpleDateFormat to complete this but when I convert the string to the format it returns the dateTime in Eastern Daylight Time and not GMT.
The value after going thru the conversion is this: "Thu Jul 04 07:00:00 EDT 2019"
This is the code that I am using to convert the string to a DateTime.
EndDate=map.get("SchEndDate2");
//EndDate : **"2019-07-04 11:00:00.0"**
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
Date databaseDateTime = formatter.parse(EndDate);
//databaseDateTime: **"Thu Jul 04 07:00:00 EDT 2019"**
Why is the format incorrect and the timezone not correctly set?
Two points.
Don’t fetch your date and time as a string from Oracle. Fetch a proper date-time object. In this case a LocalDateTime.
Don’t use SimpleDateFormat, TimeZone and Date. Those classes are poorly designed and long outdated, the first in particular notoriously troublesome. Use java.time, the modern Java date and time API.
In code:
ResultSet rs = // …;
LocalDateTime dateTime = rs.getObject("END_DT_TM_GMT", LocalDateTime.class);
String databaseDateTimeAsString = dateTime.toString();
System.out.println(databaseDateTimeAsString);
Example output:
2019-07-04T11:00
It’s not quite the output format that you asked for, but it most likely will serve your purpose. The format you asked for is ISO 8601. So is the output I have given you. In the ISO 8601 standard, including the seconds and fraction of second when they are 0 is optional. If you insist on including them, use a formatter. For example:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS");
String databaseDateTimeAsString = dateTime.format(formatter);
2019-07-04T11:00:00.000
Using rs.getObject() for getting a LocalDateTime as shown requires a JDBC 4.2 compliant database driver. You probably have got that. In case you haven’t and you cannot upgrade, use:
LocalDateTime dateTime = rs.getTimestamp("END_DT_TM_GMT").toLocalDateTime();
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
Try converting the Date object to an Instant. Here's an example showing your input string first converted to a Date, and then converting that to an Instant. The date contains the timezone-specific rendering, but the instant does not.
String input = "2019-07-04 11:00:00.0";
System.out.println("input: " + input);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date = formatter.parse(input);
System.out.println("date: " + date);
Instant instant = date.toInstant();
System.out.println("instant: " + instant);
And here's the output:
input: 2019-07-04 11:00:00.0
date: Thu Jul 04 05:00:00 MDT 2019
instant: 2019-07-04T11:00:00Z
I have a date in this format (Thu Feb 11 00:00:00 GMT 530 2016) which is a string and I want to convert this to a simple date format (dd/mm/yyyy).
I have used the below code but it does not work:
SimpleDateFormat fmt123 = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
try {
refDt = fmt123.parse(refDate);
logger.log(Level.SEVERE, "date after parsing "+refDt);
}
catch (ParseException e1) {
e1.printStackTrace();
}
It gives me the result of: Tue Feb 12 00:00:00 UTC 530
How can I convert this?
What you want to achieve is a two-step process.
Step 1 - Parsing existing string
You are very close, but as you've noticed the 530 part (I guess it is milliseconds) is parsed as year.
Use following code to create the instance of SimpleDateFormat used for parsing
new SimpleDateFormat("EEE MMM dd HH:mm:ss z SSS yyyy")
Step 2 - Formatting
Once you've parsed your date object, you'd need to present it to the user. Typically you would use new SimpleDateFormat("dd/MM/yyyy") and use it to output the date. This will use your local machine settings (such as timezone) to do the formatting. Usually it is sufficient.
But this is far more complex...
Timezones - the same time will mean a different date in different timezones. What is 2 AM, 11 Feb 2016 in Europe/Amsterdam is 8 PM, 10 Feb 2016 in America/Boston (or correct me if I am wrong).
Different calendar - you've probably already heart about Gregorian, Julian or Chinese calendar. The same time moment might have different days/month or year if expressed in different calendars. Fortunately majority of time we're talking about Gregorian calendar...
There is a very nice article Date and time in Java that describes the complexities in more details.
Poor Format
That String Thu Feb 11 00:00:00 GMT 530 2016 apparently has a bad format. I assume the 530 is an offset-from-UTC. But it lacks a + or -, a serious omission. Also, while not required, a padding zero on a single-digit hour of an offset is advised (05 rather than 5).
FYI, +05:30 is the time zone for two time zones, Asia/Kolkata and for Asia/Colombo. See this list. No time zone has an offset of -05:30.
I suspect this string may not actually be parseable as-is. You will need to manipulate the input string before attempting a parse. Something like the following, but your code will have to be more flexible if your input strings may vary.
String input = "Thu Feb 11 00:00:00 GMT 530 2016".replace ( "GMT 530" , "GMT+05:30" );
java.time
The Question and other Answers use the old outmoded date-time classes. Classes such as java.util.Date/.Calendar & java.text.SimpleDateFormat have been supplanted by the java.time framework built into Java 8 and later.
The formatter codes in java.time are a bit different than those of SimpleTextFormat. Be sure to read the doc.
String input = "Thu Feb 11 00:00:00 GMT 530 2016".replace ( "GMT 530" , "GMT+05:30" );
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "EEE MMM dd HH:mm:ss z uuuu" );
ZonedDateTime zdtGmt = ZonedDateTime.parse ( input , formatter );
ISO 8601
The java.time classes use ISO 8601 formats by default in their toString method implementations.
String output = zdtGmt.toString ();
Time Zone
Let’s adjust into the specific time zone of Asia/Kolkata rather than GMT. A time zone is an offset-from-UTC plus a set of past, present, and future adjustment rules for anomalies such as Daylight Saving Time.
ZonedDateTime zdtAsiaKolkata = zdtGmt.withZoneSameInstant ( ZoneId.of ( "Asia/Kolkata" ) );
Dump to console.
System.out.println ( "input: " + input + " | zdtGmt: " + zdtGmt + " | output: " + output + " | zdtAsiaKolkata: " + zdtAsiaKolkata );
input: Thu Feb 11 00:00:00 GMT+05:30 2016 | zdtGmt: 2016-02-11T00:00+05:30[GMT+05:30] | output: 2016-02-11T00:00+05:30[GMT+05:30] | zdtAsiaKolkata: 2016-02-11T00:00+05:30[Asia/Kolkata]
Your format here
SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
should match your input
"Thu Feb 11 00:00:00 GMT 530 2016"
As is mentioned in the comments this causes the parses to think 530 is the year and it ignores the rest.
See SimpleDateFormat for details.
SimpleDateFormat fmt123 = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");
try {
refDt = fmt123.parse(refDate);
logger.log(Level.SEVERE, "date after parsing "+refDt);
}
catch (ParseException e1) {
e1.printStackTrace();
}
I'm working on a critical application which cares about daylight saving time change.
I'm trying to simulate manually what could happen at runtime by comparing thow date which cross the daylight saving change, so I made the below test.
My current location is Italy so the change from CEST (Central European Summer Time) to CET (Central European Time) this year happens on 25/10.
I used the full time zone names, my timezone is Europe/Rome.
And here it is the test I did:
Calendar before = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome DST")); //CEST
before.set(Calendar.DAY_OF_MONTH, 25);
before.set(Calendar.MONTH, Calendar.OCTOBER);
before.set(Calendar.HOUR_OF_DAY, 2);
before.set(Calendar.MINUTE, 30);
before.set(Calendar.SECOND, 0);
before.set(Calendar.MILLISECOND, 0);
System.out.println(before.getTime());
Calendar after = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome")); //CET
after.set(Calendar.DAY_OF_MONTH, 25);
after.set(Calendar.MONTH, Calendar.OCTOBER);
after.set(Calendar.HOUR_OF_DAY, 2);
after.set(Calendar.MINUTE, 30);
after.set(Calendar.SECOND, 0);
after.set(Calendar.MILLISECOND, 0);
System.out.println(after.getTime());
System.out.println(before.compareTo(after));
The output is:
BEFORE DST CHANGE: Sun Oct 25 03:30:00 CET 2015
AFTER DST CHANGE: Sun Oct 25 02:30:00 CET 2015
before.compareTo(after): 1
The comparison result is wrong, i.e. 2:30 CEST is after 2:30 CET, but its the opposite.
I don't know if it's a real test.
Is it Is there any way to fix this?
I tried also with joda time but the result is the same.
Thanks in advance.
Your problem is that "Europe/Rome DST" is not recognized by getTimeZone(timeZoneId).
When it doesn't understand your input, it returns the GMT timezone by default. You can see the list of available TimeZone ids with getAvailableIDs (the method below getTimeZone at the above link).
It should be noted that CEST is also not on the list. To simulate the CEST timezone you could choose one of the following solutions:
I would recommend using TimeZone.setRawOffset(int offsetInMs) to set the offests for CET and CEST yourself.
Use one of the timzones that is defined relative to GMT (ex, with id "Etc/GMT+1"). This will ensure that you are using valid timezone offsets the the TimeZone api will understand.
Set the DST offset on the calendar instance Calendar.DST_OFFSET.
By using the last solution the correct test code is:
Calendar before = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome"));
before.set(Calendar.DST_OFFSET, 3600000);
before.set(Calendar.DAY_OF_MONTH, 25);
before.set(Calendar.MONTH, Calendar.OCTOBER);
before.set(Calendar.HOUR_OF_DAY, 2);
before.set(Calendar.MINUTE, 30);
before.set(Calendar.SECOND, 0);
before.set(Calendar.MILLISECOND, 0);
System.out.println("BEFORE DST CHANGE: " + before.getTime());
Calendar after = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome"));
after.set(Calendar.DAY_OF_MONTH, 25);
after.set(Calendar.MONTH, Calendar.OCTOBER);
after.set(Calendar.HOUR_OF_DAY, 2);
after.set(Calendar.MINUTE, 30);
after.set(Calendar.SECOND, 0);
after.set(Calendar.MILLISECOND, 0);
System.out.println("AFTER DST CHANGE: " + after.getTime());
System.out.println("before.compareTo(after): " + before.compareTo(after));
And the output:
BEFORE DST CHANGE: Sun Oct 25 02:30:00 CEST 2015
AFTER DST CHANGE: Sun Oct 25 02:30:00 CET 2015
before.compareTo(after): -1
The answer by augray is correct and should be accepted (click that large empty check mark icon to make it turn green). I'll add some thoughts and code.
Use A Good Date-Time Library
Avoid the mess that is the java.util.Date/.Calendard classes. They are notoriously troublesome, flawed in both design and implementation.
These classes have been supplanted by the new java.time package in Java 8 and later (Tutorial). That package was inspired by the Joda-Time library. While similar, java.time and Joda-Time are not identical. Each has features the other lacks. You can use either or both.
Avoid 3-4 Letter Time Zone Codes
Codes such as CET & CEST are neither standardized nor unique. Avoid them.
Use full time zone names. Most of these are "continent/city" or "continent/region".
You seem to be using this codes in an effort to manage the problem of DST, Daylight Saving Time. Leave such heavy-lifting to the date-time library, such as java.time or Joda-Time. A time zone combines an offset from UTC with the set of past, present, and future rules for DST and other anomalies. So you specify the time zone name and let the library do the work of figuring out when DST is in effect.
DST
Daylight Saving Time (DST) for Rome ends this year on October 25, 2015 at 3 AM. Clocks are rolled back to repeat the 2 AM hour. So there are two 2:30 times that day. You can see both of those 2:30 times in example code below.
2015-10-25T02:30+02:00[Europe/Rome]
2015-10-25T02:30+01:00[Europe/Rome]
Example Code
Here is some example code in java.time of Java 8 to see how DST is handled. First we take some "local" date-time, where "local" means without any particular time zone attached. We then assign the Rome time zone. After that we take the zoned values (the Rome values) and either add or subtract hours.
Ambiguity
Note how the notion of "2:30 AM in Rome" is meaningless on the 25th of October. You must know the offset of 01:00 or 02:00 to correctly interpret.
ZoneId zone = ZoneId.of( "Europe/Rome" );
System.out.println( "-----| Local |-----------------------------------------\n" );
LocalDateTime local_0130 = LocalDateTime.of( 2015 , Month.OCTOBER , 25 , 1 , 30 );
ZonedDateTime zoned_0130 = ZonedDateTime.of( local_0130 , zone );
LocalDateTime local_0230 = LocalDateTime.of( 2015 , Month.OCTOBER , 25 , 2 , 30 );
ZonedDateTime zoned_0230 = ZonedDateTime.of( local_0230 , zone );
LocalDateTime local_0330 = LocalDateTime.of( 2015 , Month.OCTOBER , 25 , 3 , 30 );
ZonedDateTime zoned_0330 = ZonedDateTime.of( local_0330 , zone );
System.out.println( "local_0130: " + local_0130 + " in zone: " + zone + " is " + zoned_0130 );
System.out.println( "local_0230: " + local_0230 + " in zone: " + zone + " is " + zoned_0230 );
System.out.println( "local_0330: " + local_0330 + " in zone: " + zone + " is " + zoned_0330 + "\n" );
System.out.println( "-----| Add Hours |-----------------------------------------\n" );
ZonedDateTime zoned_0130_plus_1H = zoned_0130.plusHours( 1 );
ZonedDateTime zoned_0130_plus_2H = zoned_0130.plusHours( 2 );
System.out.println( "zoned_0130_plus_1H: " + zoned_0130_plus_1H );
System.out.println( "zoned_0130_plus_2H: " + zoned_0130_plus_2H + "\n" );
System.out.println( "-----| Subtract Hours |-----------------------------------------\n" );
ZonedDateTime zoned_0330_minus_1H = zoned_0330.minusHours( 1 );
ZonedDateTime zoned_0330_minus_2H = zoned_0330.minusHours( 2 );
System.out.println( "zoned_0330_minus_1H: " + zoned_0330_minus_1H );
System.out.println( "zoned_0330_minus_2H: " + zoned_0330_minus_2H + "\n" );
When run.
-----| Local |-----------------------------------------
local_0130: 2015-10-25T01:30 in zone: Europe/Rome is 2015-10-25T01:30+02:00[Europe/Rome]
local_0230: 2015-10-25T02:30 in zone: Europe/Rome is 2015-10-25T02:30+02:00[Europe/Rome]
local_0330: 2015-10-25T03:30 in zone: Europe/Rome is 2015-10-25T03:30+01:00[Europe/Rome]
-----| Add Hours |-----------------------------------------
zoned_0130_plus_1H: 2015-10-25T02:30+02:00[Europe/Rome]
zoned_0130_plus_2H: 2015-10-25T02:30+01:00[Europe/Rome]
-----| Subtract Hours |-----------------------------------------
zoned_0330_minus_1H: 2015-10-25T02:30+01:00[Europe/Rome]
zoned_0330_minus_2H: 2015-10-25T02:30+02:00[Europe/Rome]
My advice is to use the full identifiers from the IANA time zone database. In your case you should be using "Europe/Rome":
before.setTimeZone(TimeZone.getTimeZone("Europe/Rome"));
This will make sure that proper time zone info is used for the region, including when daylight saving mode needs to be triggered, and possible regional exceptions.
Do not add DST.
"Europe/Rome" is not CET, and "Europe/Rome DST" is not CEST.
"Europe/Rome" is the timezone of Italy. It includes not only DST changes, but any other change to the offset that Rome/Italy has had. So "Europe/Rome" is CET when Rome is in CET and it's CEST when Rome is on CET. The whole point of timezones like "Europe/Rome" is that you don't have to care about daylight savings, the timezone will handle it for you.
I'm working on some code that takes care of timezone differences (in this case, converting a date from UTC to EST/EDT) and I noticed that I'm getting the incorrect DATE field from the Calendar variable.
Here are the log excerpts from the timezone change:
UTC time: Fri Nov 15 00:28:44 EST 2013
America/New_York time: Thu Nov 14 19:28:44 EST 2013
The code is correctly updating the time to the 14th, based on what shows up with Calendar.getTime(), but when I call Calendar.get(Calendar.DATE), I'm still getting 15 as the date.
Why are the fields not updating when the time itself is?
Code excerpt:
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
TimeZone fromTz = TimeZone.getTimeZone("UTC");
TimeZone toTz = TimeZone.getTimeZone("America/New_York");
jlog.info(fromTz.getID() + " time: " + cal.getTime().toString());
cal.setTimeZone(fromTz);
// Finds the difference between the two timezones based on their offset from UTC (in the case of the system timezone changing in the future).
long currentTime = System.currentTimeMillis();
int timeDifference = toTz.getOffset(currentTime) - fromTz.getOffset(currentTime);
cal.add(Calendar.MILLISECOND, timeDifference);
if (dst) { // Logic for determining whether or not the extra hour for DST is needed.
cal.add(Calendar.MILLISECOND, fromTz.getDSTSavings());
}
jlog.info(toTz.getID() + " time: " + cal.getTime().toString());
jlog.info(cal.getTime().toString() + " - " + cal.get(Calendar.DATE));
Output for the above code:
UTC time: Fri Nov 15 00:28:44 EST 2013
America/New_York time: Thu Nov 14 19:28:44 EST 2013
Thu Nov 14 19:28:44 EST 2013 - 15
NOTE: Please don't suggest that I use Joda-time. I'm just looking for an answer to this question as is.
If it's not solvable because Calendar/Date are terrible packages, that's fine - I'll just parse the date myself to get the correct values. Thanks in advance.
You haven't shown us enough code to know what's going on, but your output is very easy to explain: you're calling Date.toString() which always formats the instant in time using the system local time zone. The time zone in the Calendar object is irrelevant.
So it looks like your Calendar may be in UTC for example, in which case the day is 15.
Note that the first line of your log is clearly nonsense:
UTC time: Fri Nov 15 00:28:44 EST 2013
It's either UTC or it's EST. It can't be both.
It's not clear where your data comes from or exactly how you're dealing with it, but if you're manually adjusting the date/time by adding or subtracting parts, you're almost certainly doing it wrong. It's very important to understand that a java.util.Date doesn't have any notion of a time zone as part of its data - it's just an instant in time.
To format a Date in a particular time zone, you'd usually use a SimpleDateFormat and specify the time zone on that. For example:
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println("The time in New York is " + format.format(new Date()));
EDIT: Now that we've seen your code, you should definitely not do things that way. You're adjusting the point in time, which isn't what you want - you only want to change your view on the same point in time, which can be achieved using Calendar.setTimeZone to change what's returned by Calendar.get, and using DateFormat.setTimeZone to change which time zone is used for parsing/formatting text.
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.LocalDate;
import java.time.LocalTime;
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) {
ZonedDateTime zdtUtc = ZonedDateTime.of(LocalDate.of(2013, 11, 15), LocalTime.of(0, 28, 44),
ZoneId.of("Etc/UTC"));
ZonedDateTime zdtNewYork = zdtUtc.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println(zdtNewYork);
// Custom format
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z uuuu", Locale.ENGLISH);
System.out.println(zdtNewYork.format(dtf));
}
}
Output:
2013-11-14T19:28:44-05:00[America/New_York]
Thu Nov 14 19:28:44 EST 2013
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.
If I understand your question, you could do it with something like this -
Calendar c = Calendar.getInstance();
DateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy",
Locale.ENGLISH);
formatter.setTimeZone(TimeZone.getTimeZone("UTC")); // <-- Set the timezone on the
// DateFormat
/* Your input date/time */
c.setTime(new GregorianCalendar(2013, 10, 15, 0, 28, 44).getTime());
System.out.println(formatter.format(c.getTime()));
c.setTimeZone(TimeZone.getTimeZone("EST"));
System.out.println(c.getTime());
The output of this code is
Fri Nov 15 05:28:44 UTC 2013
Fri Nov 15 00:28:44 EST 2013