I have date formats as: EEE, dd MMM yyyy HH:mm:ss Z
For ex.,
Date 1 : Mon Sep 10 08:32:58 GMT 2018
Date 2 : Tue Sep 11 03:56:10 GMT 2018
I need date difference as 1 in above case, but I am getting value as 0 if I use joda date time or manually converting date to milliseconds.
For reference : http://www.mkyong.com/java/how-to-calculate-date-time-difference-in-java/
Any leads will be helpful.
Example :
Date date1 = new Date("Mon Sep 10 08:32:58 GMT 2018");
Date date2 = new Date("Tue Sep 11 03:56:10 GMT 2018");
DateTime start = new DateTime(date1 );
DateTime end = new DateTime(date2);
int days = Days.daysBetween(start, end).getDays();
System.out.println("Date difference: " + days);
Output: Date difference: 0
Joda-Time counts only whole days, in other words, truncates the difference to a whole number. So with a little over 19 hours between your values it counts as 0 days. If you want to ignore the time part of the dates, convert to LocalDate first:
int days = Days.daysBetween(start.toLocalDate(), end.toLocalDate()).getDays();
(Thanks for providing the concrete code yourself in a comment. Since you said it worked, I thought it deserved to be an answer.)
As mentioned in previous comments, Joda-Time counts whole days and rounds down. Therefore you'll need to skip the time when comparing. Something like this will work, using Java.time comparing the dates:
Date date1 = new Date("Mon Sep 10 08:32:58 GMT 2018");
Date date2 = new Date("Tue Sep 11 03:56:10 GMT 2018");
LocalDate start = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate end = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
long between = ChronoUnit.DAYS.between(start, end);
System.out.println("Date difference: " + between);
Related
This question already has answers here:
Why when year is less than 1884, it remove few milliseconds?
(2 answers)
Closed 3 years ago.
This is not a duplicate as some people think. It is about two standard Java classes for formatting dates that produce different strings for the same value of milliseconds since the epoch.
For values of milliseconds since the epoch that occur before some point in the year 1883, SimpleDateFormat and DateTimeFormatter will produce different results. For reasons I don't understand, DateTimeFormatter will produce strings that differ from what I expect by almost four minutes.
This is important because I am changing some code to use DateTimeFormatter instead of SimpleDateFormat. Our input is always milliseconds since the epoch, and I need the values to be the same after I change the code.
The previous code would create a Date from the milliseconds, then use SimpleDateFormat to format it.
The new code creates an Instant from the milliseconds, then a ZonedDateTime from the Instant, then a DateTimeFormatter to format it.
Here's a test I wrote using JUnit4 and Hamcrest. The test finds the milliseconds since the epoch for May 13, 15:41:25, for each year starting at 2019 and working backwards one year at a time.
For each year, it formats the milliseconds using SimpleDateFormat and DateTimeFormatter then compares the results.
#Test
public void testSimpleDateFormatVersusDateTimeFormatter() throws Exception {
String formatString = "EEE MMM dd HH:mm:ss zzz yyyy";
String timeZoneCode = "America/New_York";
ZoneId zoneId = ZoneId.of(timeZoneCode);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatString);
simpleDateFormat.setTimeZone(TimeZone.getTimeZone(timeZoneCode));
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatString);
for (int year = 0; year < 200; year++) {
long millis = getMillisSinceEpoch(2019 - year, 5, 13, 15, 41, 25, timeZoneCode);
System.out.printf("%s%n", new Date(millis));
// Format using a DateTimeFormatter;
Instant instant = Instant.ofEpochMilli(millis);
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, zoneId);
String dateTimeFormatterString = dateTimeFormatter.format(zonedDateTime);
// Format using a SimpleDateFormat
Date date = new Date(millis);
String simpleDateFormatString = simpleDateFormat.format(date);
System.out.println("dateTimeFormatterString = " + dateTimeFormatterString);
System.out.println("simpleDateFormatString = " + simpleDateFormatString);
System.out.println();
assertThat(simpleDateFormatString, equalTo(dateTimeFormatterString));
}
}
private long getMillisSinceEpoch(int year, int month, int dayOfMonth, int hours, int minutes, int seconds, String timeZoneId) {
TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);
Calendar calendar = Calendar.getInstance(timeZone);
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month-1);
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
calendar.set(Calendar.HOUR_OF_DAY, hours);
calendar.set(Calendar.MINUTE, minutes);
calendar.set(Calendar.SECOND, seconds);
return calendar.getTimeInMillis();
}
Running this you can see it passes for all years from 2019 back to 1884. So for any given year you see output like this:
Mon May 13 12:41:25 PST 1895
dateTimeFormatterString = Mon May 13 15:41:25 EST 1895
simpleDateFormatString = Mon May 13 15:41:25 EST 1895
But once it gets to 1883 it inexplicably fails:
Sun May 13 12:41:25 PST 1883
dateTimeFormatterString = Sun May 13 15:45:23 EST 1883
simpleDateFormatString = Sun May 13 15:41:25 EST 1883
java.lang.AssertionError:
Expected: "Sun May 13 15:45:23 EST 1883"
but: was "Sun May 13 15:41:25 EST 1883"```
The hours and seconds are obviously wrong.
By the way, if I change the time zone to "UTC", then the test passes.
According to https://www.timeanddate.com/time/change/usa/new-york?year=1883 (which was the first hit in a Google search for "1883 time adjustment"):
Nov 18, 1883 - Time Zone Change (LMT → EST)
When local standard time was about to reach
Sunday, November 18, 1883, 12:03:58 pm clocks were turned backward 0:03:58 hours to
Sunday, November 18, 1883, 12:00:00 noon local standard time instead.
3:58 matches the "almost four minutes" that you're seeing.
I haven't tested this, but I bet that if you iterate through months and days in addition to years, it occurs at that date.
See Also
Why when year is less than 1884, it remove few milliseconds?
Python pytz timezone conversion returns values that differ from timezone offset for different dates
Why is subtracting these two times (in 1927) giving a strange result? — a classic answered by Jon Skeet; not the same issue, but the same kind of issue
The Times Reports on "the Day of Two Noons"
I tried the below approach and searched in Web to find the solution for this but no luck : looking for the solution for converting a String in IST to PST:
String string = new Date().toString();
System.out.println(string);
SimpleDateFormat dt = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
dt.setTimeZone(TimeZone.getTimeZone("PST"));
Date D = dt.parse(string);
System.out.println(""+ D);
Even when I set time zone as PST, I am seeing out put in IST
here is the out put:
Tue Apr 18 18:58:09 IST 2017
Tue Apr 18 18:58:09 IST 2017
I tried another Option here I am seeing even it is showing the time in PST but I see below output it is a bit confusing:
public static Date convertFromOneTimeZoneToOhter(Date dt,String from,String to ) {
TimeZone fromTimezone =TimeZone.getTimeZone(from);//get Timezone object
TimeZone toTimezone=TimeZone.getTimeZone(to);
long fromOffset = fromTimezone.getOffset(dt.getTime());//get offset
long toOffset = toTimezone.getOffset(dt.getTime());
//calculate offset difference and calculate the actual time
long convertedTime = dt.getTime() - (fromOffset - toOffset);
Date d2 = new Date(convertedTime);
return d2;
}
OUT PUT:
Converted Date : Tue Apr 18 06:28:09 IST 2017
Can someone please help on this: I found lot of solutions on converting IST Date time to PST String but not IST/EST Date to PST Date.
As I mentioned above we can format to a String, but I am looking for an example of converting back to Date
You should look into Java 8's new Date API that handles timezones directly
// Get the current date and time
ZonedDateTime date1 = ZonedDateTime.parse("2007-12-03T10:15:30+05:30[Asia/Karachi]");
System.out.println("date1: " + date1);
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println("Zoned Date Time: " + zonedDateTime);
ZoneId id = ZoneId.of("Europe/Paris");
System.out.println("ZoneId: " + id);
ZoneId currentZone = ZoneId.systemDefault();
System.out.println("CurrentZone: " + currentZone);
Prints :
date1: 2007-12-03T10:15:30+05:00[Asia/Karachi]
Zoned Date Time: 2017-04-18T09:52:09.045-04:00[America/New_York]
ZoneId: Europe/Paris
CurrentZone: America/New_York
Since some readers here will use Java 8 or later and some Java 7 or earlier, I will treat both.
I recommend you use the java.time classes introduced in Java 8 if you can:
ZoneId targetTz = ZoneId.of("America/Los_Angeles");
String string = "Tue Apr 18 18:58:09 +0300 2017";
DateTimeFormatter format = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss ZZZ uuuu",
Locale.ENGLISH);
ZonedDateTime sourceTime = ZonedDateTime.parse(string, format);
ZonedDateTime targetTime = sourceTime.withZoneSameInstant(targetTz);
String result = targetTime.format(format);
System.out.println(result);
This prints:
Tue Apr 18 08:58:09 -0700 2017
You said you wanted a PST date, and this is exactly what the ZonedDateTime gives you: date and time with time zone information.
In the example I am giving a zone offset, +0300 (corresponding to Israel Daylight Time) in the string. I understood that it wasn’t important to you how the time zone was given. I want to avoid the three and four letter time zone abbreviations like IST. Not only may IST mean either Irish Standard Time, Israel Standard Time or India Standard Time. I furthermore noticed that the java.time classes pick up 18:58:09 IST as 18:58:09 IDT (UTC+3) because it knows Israel is on DST on April 18; the SimpleDateFormat that I return to below takes IST more literally and interprets 18:58:09 IST as 18:58:09 +0200, which is 1 hour later in UTC.
You can use the java.time classes with Java 1.7 if you want. You can get them in the ThreeTen Backport.
If you don’t want to use java.time, the way to do it with the outdated classes from Java 1.0 and 1.1 is not that different in this case, only I cannot give you the PST date you asked for:
TimeZone targetTz = TimeZone.getTimeZone("America/Los_Angeles");
String string = "Tue Apr 18 18:58:09 +0300 2017";
SimpleDateFormat dt = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy", Locale.ENGLISH);
Date d = dt.parse(string);
dt.setTimeZone(targetTz);
String result = dt.format(d);
System.out.println(result);
It prints the same result as above. However, you notice there is only one Date object. A Date object cannot hold any time zone information, so if you need this, you will have to bring the targetTz object along with d. It’s a common misunderstanding that there’s supposed to be a time zone in the Date object, probably greatly helped by the fact that its toString() prints a time zone. This is always the JVM’s default time zone and doesn’t come from the Date object, though.
I am working on an Android app that will display a list of activities. Every activity (i.e. waling, running) has a property Date (i.e. 9 March 8:58 2017). I have two buttons on the screen - Daily and Weekly and I want to switch betweren the two and change the list accordingly. Now, for the Daily list, I don't have to change anything, since a new Activity is created for every day.
However, I am not sure how to go about the Weekly list. It will essentially calculate stats (adding up the statistics for the individual weeks).
For example, I have a list of dates for the last 50 days. How to distinguish an individual list of Dates that would represent an individual week so I can construct a list of Weeks? Basically, convert those 50 dates into their week equivalent (e.g. about 7 weeks)
This is a test list of Dates that I am trying to get working first:
HashMap<Integer,Date> dateHashMap = new HashMap<>();
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
List<Date> dates = new ArrayList<>();
dates.add(sdf.parse("10/03/2017"));
dates.add(sdf.parse("9/03/2017"));
dates.add(sdf.parse("8/03/2017"));
dates.add(sdf.parse("7/03/2017"));
dates.add(sdf.parse("6/03/2017"));
dates.add(sdf.parse("23/02/2017"));
dates.add(sdf.parse("3/02/2017"));
dates.add(sdf.parse("2/02/2017"));
dates.add(sdf.parse("1/02/2017"));
for(Date d:dates){
dateHashMap.put(d.getDay(),d);
}
System.out.println(dateHashMap.toString());
An example UI design that I am trying to achieve:
As you already have Date property for each activity, then its quite simple actually
First just decide how you want your weeks
ex: I would just go from Mon to Sun as one week
So here Week nth will have dates - 1st to 5th March and Week nth+1 will have 6th to 12th March and so on..
and as far as i can understand you already have every activity (i.e. waling, running) with a property Date (i.e. 9 March 8:58 2017)
So taking an example here (let me know if this isn't how you have your data) :
waling - 1 March 2017 8:58 to 9:58, 3 March 2017 6:20 to 6:50, 8 March 2017 12:00 to 13:00
running - 2 March 2017 6:10 to 8:00, 3 2017 March 7:00 to 8:00, 9 March 2017 5:50 to 7:00
Now data for Week nth you can calculate by adding up duration for waling activity for dates 1st and 3rd March as waling was present only on these dates on Week nth of March 2017 and similarly for week nth+1 and so on
Same goes for running activity for week nth adding up for dates 2nd March, 3rd March and similarly for week nth+1 and so on..
Now you will have something like :
Week nth :
Wailing - 1 hr and 30 min
Running - 2 hrs and 50 min
Week nth+1 :
Wailing - 1 hr
Running - 1 hr and 10 min
And on clicking of each activity you can show some more details..
Hope this helps :)
Edit :
Considering this is how you have your dates list
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
List<Date> dates = new ArrayList<>();
try {
dates.add(sdf.parse("10/03/2017"));
dates.add(sdf.parse("9/03/2017"));
dates.add(sdf.parse("8/03/2017"));
dates.add(sdf.parse("7/03/2017"));
dates.add(sdf.parse("6/03/2017"));
dates.add(sdf.parse("23/02/2017"));
dates.add(sdf.parse("3/02/2017"));
dates.add(sdf.parse("2/02/2017"));
dates.add(sdf.parse("1/02/2017"));
} catch (ParseException e) {
e.printStackTrace();
}
You can create a custom List just to identify the dates that falls in the same week ex (I just used what #Jameson suggested in his answer, you can always write this a lot better):
public List<WeekDay> getListOfWeeksFromListOfDates(List<Date> listOfDates) {
List<WeekDay> listOfWeeks = new ArrayList<>();
WeekDay weekDay;
for (Date date : listOfDates) {
weekDay = new WeekDay(date, new SimpleDateFormat("w").format(date));
listOfWeeks.add(weekDay);
}
return listOfWeeks;
}
public class WeekDay {
Date date;
String weekIdentifier;
public WeekDay(Date Date, String WeekIdentifier) {
this.date = Date;
this.weekIdentifier = WeekIdentifier;
}
public Date getDate() {
return date;
}
public String getWeekIdentifier() {
return weekIdentifier;
}
}
And you can use getListOfWeeksFromListOfDates(dates); to have a list with Dates and Week number, this week number can serve as an identifier to compare the dates and then you can add the activities for dates with same Week number.. Hope you are getting what i am trying to convey here :)
/**
* Gets a list of week numbers (as strings) from a list of dates.
*
* #param listOfDates the list of dates
* #return a list of week in year (as string), corresponding
* one-to-one to the values in the input list.
*/
public List<String> getListOfWeeksFromListOfDates(List<Date> listOfDates) {
List<String> listOfWeeks = new ArrayList<>();
for (Date date : listOfDates) {
listOfWeeks.add(new SimpleDateFormat("w").format(date));
}
return listOfWeeks;
}
Week?
You have not defined what you mean by week.
Do you mean the standard ISO 8601 week where each week starts on a Monday and week # 1 contains the first Thursday, each week numbered 1-52 or 53?
Or do you mean a United States type week beginning on a Sunday with weeks numbered 1-52/53 starting with January 1, and if so are the last days of the previous week in the previous year or the new year?
Or do you mean something else?
Time zone?
What time zone do want to use as the context for determining the date? Or do you want to keep your date-times in UTC like Stack Overflow does in tracking your activity for “today” vs “yesterday”?
Avoid legacy date-time classes
The troublesome old date classes including Date and Calendar should be avoided whenever possible. They are now supplanted by the java.time classes.
Convert your given Date objects to Instant, a moment on the timeline in UTC.
Instant instant = myDate.toInstant();
ISO 8601
I suggest using the standard week whenever possible.
Adjust your Instant into the desired time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
Retrieve the standard week number.
int weekNumber = zdt.get( WeekFields.ISO.weekOfWeekBasedYear() );
Keep in mind that the year number to go with this week number is not the calendar year. We want the year of the week-based year. For example, in some years, December 30 and 31 can belong to the following year number of a week-based year.
int yearOfWeekBasedYear = zdt.get( WeekFields.ISO.weekBasedYear() );
You could track your records against a string composed of this yearOfWeekBasedYear and weekNumber. Use standard format, yyyy-Www such as 2017-W07.
ThreeTen-Extra YearWeek
Instead I suggest you use meaningful objects rather than mere strings. Add the ThreeTen-Extra library to your project to gain the YearWeek class.
This code replaces the WeekFields code we did above.
YearWeek yw = YearWeek.from( zdt );
Thanks to #shadygoneinsane and # Basil Bourque for pointing me to the right direction I solved the problem the following way:
TreeMap<Integer, List<Date>> dateHashMap = new TreeMap<>();
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
List<Date> dates = new ArrayList<>();
dates.add(sdf.parse("10/03/2017"));
dates.add(sdf.parse("9/03/2017"));
dates.add(sdf.parse("8/03/2017"));
dates.add(sdf.parse("7/03/2017"));
dates.add(sdf.parse("6/03/2017"));
dates.add(sdf.parse("23/02/2017"));
dates.add(sdf.parse("3/02/2017"));
dates.add(sdf.parse("2/02/2017"));
dates.add(sdf.parse("1/02/2017"));
for (int i = 0; i < dates.size(); i++) {
List<Date> datesList = new ArrayList<>();
Calendar calendar = Calendar.getInstance();
calendar.setTime(dates.get(i));
int weekOfMonth = calendar.get(Calendar.WEEK_OF_MONTH);
for (Date date : dates) {
Calendar c = Calendar.getInstance();
c.setTime(date);
if (weekOfMonth == c.get(Calendar.WEEK_OF_MONTH)) {
datesList.add(date);
}
}
dateHashMap.put(weekOfMonth, datesList);
}
System.out.println(dateHashMap.toString());
}
And the result:
Output:
1=[Fri Feb 03 00:00:00 GMT 2017,
Thu Feb 02 00:00:00 GMT 2017,
Wed Feb 01 00:00:00 GMT 2017],
2=[Fri Mar 10 00:00:00 GMT 2017,
Thu Mar 09 00:00:00 GMT 2017,
Wed Mar 08 00:00:00 GMT 2017,
Tue Mar 07 00:00:00 GMT 2017,
Mon Mar 06 00:00:00 GMT 2017],
4=[Thu Feb 23 00:00:00 GMT 2017]
Exactly what I needed! So now I can iterate through each week and sum up the statistics and thus formulate the "Weekly" view of the list
I am having an issue with Dates and timezones.
I have a MySQL InnoDB database which holds two fields DATE(yyyy-MM-dd) and TIME(HH:mm:ss). These are known as to be UTC (0 GMT). My computer is based in CET (+1 GMT).
• dateObject is the result from this resultSet.getTime("date_field") (java.sql.Date)
• timeObject is a result from this resultSet.getDate("time_field") (java.sql.Time)
In the database DATE is stored as 2014-02-22 and TIME 15:00
System.out.println("Untouched "+dateObject+" "+timeObject);
long date = dateObject.getTime();
long time = timeObject.getTime();
System.out.println("Touched "+new Date(date+time));
Results in the following output:
Untouched 2014-02-22 15:00:00
Touched Sat Feb 22 14:00:00 CET 2014
Why is one hour being skipped off the Touched output? I was expecting the following:
Untouched 2014-02-22 15:00:00
Touched Sat Feb 22 15:00:00 CET 2014
To rumble things up I have tried with the following also:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date(date+time)));
And result:
2014-02-22 14:00:00
All in all. I am expecting GMT+1 to show 16:00(local) and GMT+0 to display 15:00
I think I did answer ma question (Remember timeObject in the db is 15:00:00 at UTC):
TimeZone tz = TimeZone.getTimeZone("Gmt0");
SimpleDateFormat sdfFull = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdfFull.setTimeZone(tz);
Date updateDate = sdfFull.parse(dateObject.toString()+" "+timeObject.toString());
System.out.println(updateDate);
Results in what I was hoping for:
Sat Feb 22 16:00:00 CET 2014
The reason is similar to this SO-answer. But note following details about toString().
java.util.Date.toString() => output dependent on your system time zone
in format pattern "EEE MMM dd HH:mm:ss zzz yyyy"
java.sql.Date.toString() => output in format "yyyy-MM-dd" (your dateObject)
java.sql.Time.toString() => output in format "HH:mm:ss" (your timeObject)
The sql representations are not dependent on time zone. So you compare apples and peaches.
Supplementary remark:
I have invested more in testing and found:
java.sql.Date dateObj = new java.sql.Date(2014 - 1900, Calendar.FEBRUARY, 22);
Time timeObj = new Time(15, 0, 0);
Time midnight = new Time(0, 0, 0);
Date d = new Date(dateObj.getTime() + timeObj.getTime());
System.out.println("dateObj: " + dateObj + "/" + dateObj.getTime());
// dateObj: 2014-02-22/1393023600000, one hour less than a full day because of UTC-long
System.out.println("timeObj: " + timeObj + "/" + timeObj.getTime());
// timeObj: 15:00:00/50400000 => one hour less as UTC-long
System.out.println("midnight: " + midnight + "/" + midnight.getTime());
// midnight: 00:00:00/-3600000 => one hour less, negative!
System.out.println(new Date(dateObj.getTime())); // Sat Feb 22 00:00:00 CET 2014
System.out.println(new Date(timeObj.getTime())); // Thu Jan 01 15:00:00 CET 1970
System.out.println(d); // Sat Feb 22 14:00:00 CET 2014
So I strongly suspect following effect: Both dateObject and timeObject are been calculated your system time zone, therefore their utc-long values show both one hour less - the time zone offset. If you combine both in one Date-object by just summarizing up then one of both deltas gets lost because one single date object cannot take in account two offsets.
Conclusion: You tried to combine date and time by summarize their utc-longs, but this is in general a faulty approach. Date plus Date is not Date, but undefined! In domain-specific language you can only add a duration/period to a date/time. So a solution having a midnight object could be:
Date d = new Date(dateObj.getTime() + timeObj.getTime() - midnight.getTime());
System.out.println(d); // Sat Feb 22 15:00:00 CET 2014, correct - what you wanted
Today is Tuesday, February 9, 2010 and when I print the date I get the wrong date:
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date today = formatter.parse(String.format("%04d-%02d-%02d",
Calendar.getInstance().get(Calendar.YEAR),
Calendar.getInstance().get(Calendar.MONTH),
Calendar.getInstance().get(Calendar.DAY_OF_MONTH)));
System.out.println("Today is " + today.toString());
The print line results in: "Today is Sat Jan 09 00:00:00 CST 2010"
It most certainly is not Saturday Jan 09, it's Tuesday Feb 09. I'm assuming I'm doing something wrong, so can anybody let me know what's wrong here? Do I have to manually set the day of week?
Update
Note: I don't want to initialize today with new Date() because I want the hours, minutes, seconds and milliseconds initialized to 0. This is necessary so I can compare a user input date with today: if the user inputs today's date and I use the formatter to construct a Date object, then if I initialize today with new Date() and I compare the two dates- today will be after the user selected date (which is incorrect). Thus I need to initialize today at the beginning of the day without the hr/min/sec/ms.
Confusingly, Calendar months count from 0 (January) to 11 (December), so you're passing "2010-01-09" to formatter.parse() when you extract the MONTH field from the Calendar.
There's a discussion of this in a related SO question.
If you don't want to use JodaTime you could use:
Calendar calendar = Calendar.getInstance();
calendar.set( Calendar.HOUR_OF_DAY, 0 );
calendar.set( Calendar.MINUTE, 0 );
calendar.set( Calendar.SECOND, 0 );
calendar.set( Calendar.MILLISECOND, 0 );
Date today = calendar.getTime();
This is much more efficient and less error-prone than your String formatting/parsing approach.
If you can use JodaTime this is a much preferred method:
LocalDate date = new DateTime().toLocaleDate();