Java - Subtract Days from date [duplicate] - java

This question already has answers here:
How to subtract n days from current date in java? [duplicate]
(5 answers)
Closed 7 years ago.
I'm trying to subtract 5 days from a date which comes in as a string initially.
I have had a look at some of the other posts on this subject but the result i get from the code is always incorrect. The main problem is that the year value does not seem to change when the days are subtracted for example - 2012-01-01 subtract 5 days gives me 'Jan 27 2012' using this code -
cal.add(Calendar.DATE, -5);
Please help.

Did you know that, in Java, month 1 is actually February?
Date februaryTheFirst = new Date(2012,1,1); // equals 2012-02-01
This might explain what you are seeing. If you want to instantiate 2012-01-01 instead, you should do:
Date firstDayOf2012 = new Date(2012,0,1); // this is 2012-01-01
Exactly the same thing happens when dealing with Calendar:
Calendar.getInstance().set(2012,0,1); // 2012-01-01
Be sure to check the documentation for Date(int, int, int) and Calendar.set(int, int, int). Also, you could check the way you are parsing the string. If you use SimpleDateFormat.parse(...), things can be easier.
Strange, isn't it? Go figure... Just as a fun fact, IntelliJ's documentation annotates this second parameter, month, with #MagicConstant, to remember the programmer that there's something very strange going on.

Calendar.FEBRUARY is 1 and five days before 1 Feb 2012 was 27 Jab 2012.

Your implementation is correct and you are getting the correct value aslo.
Calendar's Months started with 0
0 = Jan
1 = Feb
so subtracting 5 days from 2012-01-01 will definitely returns you Jan 27 2012
something is here also which will helps you Why is January month 0 in Java Calendar?

Joda-Time
The Joda-Time 2.7 library makes this work much easier. Just call the minusDays method.
String input = "2012-01-01";
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTime = new DateTime( input, zone );
DateTime then = now.minusDays( 5 );
DateTimeFormatter formatter = DateTimeFormat.forStyle( "FF" ).withZone( zone ).withLocale( Locale.CANADA_FRENCH );
String output = formatter.print( then );
If you want the beginning of the day, add a call to withTimeAtStartOfDay. This is unnecessary in your case, when parsing a date-only string with no time-of-day.
DateTime dateTimeAtStartOfDay = new DateTime( input, zone ).withTimeAtStartOfDay();
If you want only date without time-of-day or time zone, use LocalDate instead of DateTime.
LocalDate then = new LocalDate( "2012-01-01" ).minusDays( 5 );
If you need to convert to the old java.util.Date, call toDate on the DateTime.
java.time
Java 8 has a new package, java.time. These new classes were inspired by Joda-Time but were re-architected. Both java.time and Joda-Time can solve this particular problem equally well.

Use:
cal.add(Calendar.DAY_OF_MONTH, -5)
EDIT: sorry. DAY_OF_MONTH is a synonym to DATE. Instead of 1 use Calendar.JANUARY.

This a segment of code that is working on my pc. first you have to get the calendar instance the perform your calculation.
Calendar cal = Calendar.getInstance();
System.out.println("Today : " + cal.getTime());
// Subtract 300 days from the calendar
cal.add(Calendar.DATE, -300);
System.out.println("300 days ago: " + cal.getTime());
This is the output that you will get:
Today : Wed Oct 17 10:41:23 EET 2012
300 days ago: Thu Dec 22 10:41:23 EET 2011

Related

Java Calendar Strange behaviour

I am using calendar object in java to convert an input date(year/month/date etc are getting from network ) to epoch time. I am reusing same calendar object . Sometimes the year i am getting from
network is 0 and there was no validation for this once. Once this happens the whenever i convert the date to epoch, the epoch time im getting is always negative. Is this a valid behaviour
Please find sample code and result I got while doing a unit test for this issue.
Calendar cal= Calendar.getInstance();
cal.set(Calendar.YEAR, 0);
System.out.println("time 1 : "+cal.getTimeInMillis());
System.out.println("Date 1 : "+new Date(cal.getTimeInMillis()));
cal.set(Calendar.YEAR, 2020);
System.out.println("time 2 : "+cal.getTimeInMillis());
System.out.println("Date 2 : "+new Date(cal.getTimeInMillis()));
cal.set(Calendar.YEAR, 2010);
cal.set(Calendar.MONTH, 10);
System.out.println("time 3 : "+cal.getTimeInMillis());
System.out.println("Date 3 : "+new Date(cal.getTimeInMillis()));
Output for this code is
Time 1 : -62151385126938
Date 1 : Sun Jul 04 11:51:13 IST 1
Time 2 : -125866201126938
Date 2 : Wed Jul 04 11:51:13 IST 2020
Time 3 : -125540041126938
Date 3 : Fri Nov 04 11:51:13 IST 2010
Is this an expected behaviour for java Calendar?
My JDK version is
OpenJDK Runtime Environment Corretto-8.252.09.1 (build 1.8.0_252-b09)
Edit:
There are other option/class to fix this issue, But my purpose is to find the root cause of this behaviour
I am using calendar object
Stop doing that. Never use the terrible Calendar and Date classes. Use only the modern java.time classes defined in JSR 310.
Sometimes the year i am getting from network is 0 and there was no validation for this once. Once this happens the whenever i convert the date to epoch, the epoch time im getting is always negative. Is this a valid behaviour
Yes, a negative count of milliseconds since the epoch reference of first moment of 1970 in UTC would be correct for a date with year zero. Year 0000 occurred over two thousands years ago, so that would be a very large number of milliseconds counting backwards from 1970-01-01T00:00Z.
I understand that you see Calendar returning bizarre negative numbers after resetting for contemporary years. If you want more info, see excellent Answer by Ole V.V. In my opinion: there is no purpose to investigating Calendar now that we have java.time. Let’s bury the dead, and move on.
If you must inter-operate with old code not yet updated for java.time, you can convert back and forth between the legacy classes and the modern. Look to new methods added to the old classes. Minimize your use of the old legacy classes.
if( myCalendar instanceof GregorianCalendar )
{
ZonedDateTime zdt = ( ( GregorianCalendar ) myCalendar ).toZonedDateTime() ;
}
…and…
Calendar myCalendar = GregorianCalendar.from( zdt ) ;
You said:
I am reusing same calendar object .
Stop doing that. Reusing objects of that class leads to various problems.
One of the important design considerations in java.time is the use of only immutable objects, to avoid these reuse problems.
am using calendar object in java to convert an input date(year/month/date
You do not show us this code, so I cannot help you any further.
Search Stack Overflow before posting. All this has been covered many times already.
Is this an expected behaviour for java Calendar?
My perhaps polemic answer is that Calendar pretty often behaves contrary to expectations. It has been designed and documented to do so. I understand your confusion.
There is no year 0. So a first expectation might have been that Calendar should throw an exception when you try to set the year of era to 0. With standard settings it doesn’t. Instead it extrapolates: year 0 is taken to mean the year before year 1 , so that is year 1 BC. In your output you can see that the year is 1 (not 0); but what you cannot see is the era, it’s BC, not AD (CE). So let’s add a couple of lines that print the era to your code:
Calendar cal= Calendar.getInstance();
System.out.format("Initial: Era %s year %d%n",
cal.getDisplayName(Calendar.ERA, Calendar.SHORT_STANDALONE, Locale.ENGLISH),
cal.get(Calendar.YEAR));
cal.set(Calendar.YEAR, 0);
System.out.format("Year 0: Era %s year %d%n",
cal.getDisplayName(Calendar.ERA, Calendar.SHORT_STANDALONE, Locale.ENGLISH),
cal.get(Calendar.YEAR));
System.out.println("time 1 : "+cal.getTimeInMillis());
System.out.println("Date 1 : "+new Date(cal.getTimeInMillis()));
When I ran the code just now, the output was:
Initial: Era AD year 2020
Year 0: Era BC year 1
time 1 : -62151371618330
Date 1 : Sun Jul 04 11:06:21 CET 1
Next, Calendar.YEAR means year of era, at least to a GregorianCalendar (which is the concrete subclass of Calendar of which you got an instance from Calendar.getInstance()). So when next you set YEAR, that is, year of era, to 2020, the Calendar stays before Christ (before the common era), so you get 2020 BC, more than 4000 years ago. And your milliseconds “grow” to approximately double magnitude of the already negative value.
cal.set(Calendar.YEAR, 2020);
System.out.format("Year 2020: Era %s year %d%n",
cal.getDisplayName(Calendar.ERA, Calendar.SHORT_STANDALONE, Locale.ENGLISH),
cal.get(Calendar.YEAR));
System.out.println("time 2 : "+cal.getTimeInMillis());
System.out.println("Date 2 : "+new Date(cal.getTimeInMillis()));
Year 2020: Era BC year 2020
time 2 : -125866187618330
Date 2 : Wed Jul 04 11:06:21 CET 2020
IMHO it’s a fine case for avoiding the Calendar class.
java.time
And yes, if only for other readers, there are alternatives.
First, you should not try to handle a meaningless year. I don’t know your situation and requirements, so cannot tell you what to do when you get a year that is 0 or negative, but you need to decide, and you need to check and act appropriately. What you have been doing until now is wrong, as you are aware.
Second, very obviously you should use java.time, the modern Java date and time API.
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.systemDefault());
zdt = zdt.withYear(0);
System.out.println(zdt);
System.out.println(zdt.toEpochSecond());
zdt = zdt.withYear(2020);
System.out.println(zdt);
System.out.println(zdt.toEpochSecond());
zdt = zdt.withYear(2010);
System.out.println(zdt);
0000-07-04T11:23:08.573357+00:50:20[Europe/Copenhagen]
-62151197232
2020-07-04T11:23:08.573357+02:00[Europe/Copenhagen]
1593854588
2010-07-04T11:23:08.573357+02:00[Europe/Copenhagen]
You notice in this output that the seconds since the epoch turn positive again after they have been negative. In java.time a year means the proleptic year, that is, a signed year. Proleptic year 0 is 1 BC, -1 means 2 BC, etc. So year 0 is just any other year and doesn’t incur any weird behaviour.
Also java.time does object to setting year of era to 0, which might have helped you discover earlier that you had an issue:
zdt = zdt.with(ChronoField.YEAR_OF_ERA, 0);
Exception in thread "main" java.time.DateTimeException: Invalid value for YearOfEra (valid values 1 - 999999999/1000000000): 0
at java.base/java.time.temporal.ValueRange.checkValidValue(ValueRange.java:311)
at java.base/java.time.temporal.ChronoField.checkValidValue(ChronoField.java:717)
at java.base/java.time.LocalDate.with(LocalDate.java:1048)
at java.base/java.time.LocalDateTime.with(LocalDateTime.java:970)
at java.base/java.time.ZonedDateTime.with(ZonedDateTime.java:1312)
at ovv.so.date.special.SetCalendarYear0.main(SetCalendarYear0.java:25)

How do I set a Calendar with TimeZone?

I have a timestamp that I am trying to put into a Date object, however when I use Calendar, I am running into a strange problem. I seem to be able to unable to create a Date object with the values I want:
public static void main(String args[]){
Date today = new Date();
int hour = 4, min=0, sec=0, ms=64;
Calendar cal = GregorianCalendar.getInstance();
cal.clear();
cal.setTimeZone(TimeZone.getTimeZone("EDT"));
cal.setTime(today);
cal.set(Calendar.HOUR_OF_DAY,hour);
cal.set(Calendar.MINUTE,min);
cal.set(Calendar.SECOND,sec);
cal.set(Calendar.MILLISECOND,ms);
System.out.println("Time is: "+cal.getTime());
}
This produces:
Time is: Mon Jan 13 23:00:00 EST 2014
which is not the result I am looking for.
However, if I comment out the 'setTimeZone' method call, I get the following result:
Time is: Tue Jan 14 04:00:00 EST 2014
This is the result that I am looking for but I am concerned that if I am running on a machine that is not running in the same time zone, I will not get consistent behavior.
This is the result that I am looking for but I am concerned that if I am running on a machine that is not running in the same time zone
it is the problem. The internal representation should be ok, but it prints on local timezone: representation differs from real content.
use SimpleDateFormat http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html and set TimeZone to see the date on the Zone desired.
The problem here is that Java does not know of the timezone "EDT" (Eastern Daylight Time). As a result, Calendar seems to be setting the timezone to GMT.
The timezone needed here is "America/New_York" or "EST5EDT". When either of these values are used, the correct result is produced.
The list of valid Time Zones can be obtained by calling TimeZone.getAvailableIDs()
It is unfortunate that no warnings are produced when the requested Time Zone is not found.
If you can do away with java.util.Date, you can use joda time API to conveniently set these values as desired:
For your query, you can set your already created Calendar instance as a constructor parameter to DateTime.
DateTime dt = new DateTime(cal);
System.out.println(dt.toDateTimeISO());
Output:
2014-01-14T04:00:00.064-05:00
Calendar.getTime() returns a java.util.Date object. Date objects do not know anything about timezones. The Date object that Calendar.getTime() returns does not know to what timezone the Calendar that it came from is set.
When you print a Date object (for example, by implicitly calling toString() object, as you are doing) it is formatted in the default time zone of the machine you are running it on.
If you want to print a Date in a specific timezone, use a SimpleDateFormat, and set the desired timezone on the SimpleDateFormat object. For example:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("EDT"));
// Will display the date that the calendar is set to in the EDT timezone
System.out.println(df.format(cal.getTime()));
Java Date objects represent the number of milliseconds seconds since January 1, 1970, 00:00:00 GMT due to the fact that the other methods are deprecated. The two ways to "view" a Date object directly are "getTime()" and "toString()" (using "dow mon dd hh:mm:ss zzz yyyy"). Therefore, you are formatting the GMT value to your local timezone.
When working with dates, it is best to think of them as GMT values, and then as a "formatting" exercise when viewing the date.
For comparison, here is that same kind of code but using Joda-Time 2.3.
Avoid the java.util.Date & .Calendar classes.
Never use three-letter codes for time zones. They are neither standardized nor unique. Instead use proper time zone names. In this case, use "America/New_York" or "America/Montreal".
// Use time zone names, such as from this slightly outdated list: http://joda-time.sourceforge.net/timezones.html
DateTimeZone timeZone = DateTimeZone.forID( "America/New_York" );
// Input.
int hour = 4, min = 0, sec = 0, ms = 64;
// Start with now, then adjust the time of day.
DateTime now = new DateTime( timeZone );
DateTime dateTime = now.withHourOfDay( hour ).withMinuteOfHour( min ).withSecondOfMinute( sec ).withMillisOfSecond( ms );
// If needed, translate to a java.util.Date for use with other classes.
java.util.Date date = dateTime.toDate();
Dump to console…
System.out.println( "now: " + now );
System.out.println( "dateTime: " + dateTime );
System.out.println( "date: " + date );
When run…
now: 2014-01-20T21:04:51.237-05:00
dateTime: 2014-01-20T04:00:00.064-05:00
date: Mon Jan 20 01:00:00 PST 2014

How can we check if the current system date is of 1 Month Back [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to subtract 45 days from from the current sysdate
Hi I am getting the current system date by using
Java.util.Date date = new java.util.Date();
How can i check whether my Date is One month Before date
For example if today is May 22 2011
How can i check if the date is of April 22 2011 ??
You could use JodaTime. Its DateTime class has a minusMonth-method. Use this to get the date from one month ago and then compare. See the Joda-API for more details.
Calendar cal1 = Calendar.getInstance();
cal1.setTime(theGivenDate);
Calendar cal2 = Calendar.getInstance();
cal2.add(Calendar.MONTH, -1);
if ( (cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)) &&
(cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH)) &&
(cal1.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH)) ) {
System.out.println("Given date "
+ theGivenDate + " is exactly one month ago from today");
}
You can use Joda DateTime [http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html] for this.
DateTime has a method minusMonths(int months), and then you can convert Joda DateTime to java.util.Date
Are you aware that many dates will never be "one month before today" according to your definition for month as "calendar month"? For example, since June has only 30 days, the condition will never be true for May 31st.
You may want to change your definition to that commonly used by banks for purposes like calculating interest and deposit terms: a month is considered to be exactly 30 days, independent of calendar dates. So "one month after" May 31st would be June 30th.

Joda-Time, Daylight Saving Time change and date time parsing

I have the following problem using Joda-Time for parsing and producing date and time around Daylight Saving Time (DST) hours. Here is an example (please, note that March 30th 2008 is Daylight Saving change in Italy):
DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");
DateTime x = dtf.parseDateTime("30/03/2008 03:00:00");
int h = x.getHourOfDay();
System.out.println(h);
System.out.println(x.toString("dd/MM/yyyy HH:mm:ss"));
DateTime y = x.toDateMidnight().toDateTime().plusHours(h);
System.out.println(y.getHourOfDay());
System.out.println(y.toString("dd/MM/yyyy HH:mm:ss"));
I get the following output:
3
30/03/2008 03:00:00
4
30/03/2008 04:00:00
When i parse hour I get hour is 3. In my data structure I save the day storing midnight time, and then I have some value for each hour of the day (0-23). Then, when I write out the date, I re-compute the full date time making midnight plus hour. When I sum 3 hours to my midnight I get 04:00:00! And if I parse it again, I get hour 4!
Where is my mistake? Is there some way to get hour 2 when I parse or get hour three when I print out?
I have also tried to build output by hand:
String.format("%s %02d:00:00", date.toString("dd/MM/yyyy"), h);
but in this case for hour 2, I produce 30/03/2008 02:00:00 which is not a valid date (since hour 2 does not exist) and cannot be parsed any more.
Thank you in advance for your help.
Filippo
When I sum 3 hours to my midnight I get 04:00:00! And if I parse it again, I get hour 4! Where is my mistake?
You mentioned already that this date is exactly when the time changes. So there is no mistake. March 30, 2010 00:00 CEST (the timezone in Italy) is precisely speaking March 29, 2010 23:00 UTC. When you add 3 hours, you will get March 30, 2010 02:00 UTC. But this is post the moment, that we switch times (which happens on 01:00 UTC), so when you convert time to local timezone you get March 30, 04:00. That's correct behavior.
Is there some way to get hour 2 when I parse or get hour three when I print out?
No, because March 30, 2010 02:00 CEST does not exist. Precisely at March 30, 2010 01:00 UTC we switch time from +1 hour to +2 hours versus UTC, so March 30, 2010 00:59 UTC is March 30, 2010: 01:59 CEST, but March 30, 2010 01:00 UTC become March 30, 2010 03:00 CEST. No 02:xx hour exist on that particular date.
BTW. In a week you can expect another "fun". Can you tell what date in UTC this refers to:
October 31, 2010 02:15 CEST ?
Well, the funny part is, we do not know. It could be either 0ctober 31, 2010 00:15 UTC (before actual time switch) or October 31, 2010 01:15 UTC (after the switch).
That's exactly why you should always store date and times in relation to UTC and convert them to local time zone before displaying, otherwise you risk an ambiguity.
HTH.
The data structure you are saving your data is not very optimal for the days with daylight saving time. Your day in this particular day should only have 23 hours.
If you do:
DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss").withLocale(Locale.US);
DateTime x = dtf.parseDateTime("30/03/2008 00:00:00");
DateTimeFormatter parser = DateTimeFormat.fullDateTime();
System.out.println("Start:"+parser.print(x));
DateTime y = x.plusHours(4);
System.out.println("After add of 4:"+parser.print(y));
You get the expected result, that the time is 05:00.
I recommend that you change the way you store your day and use a date. If not, you must handle daylight saving time when storing the hour of day.
You might do something like this:
In the case where we move the time forward one hour, as this case, you must store 4 and not 5 as the time for 5. And when you calculate the time, you should use the plusHours() method to get the actual time. I think you might get away with something like:
public class DateTest {
private static final int HOUR_TO_TEST = 2;
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");
DateTime startOfDay = dtf.parseDateTime("30/03/2008 00:00:00");
/* Obtained from new DateTime() in code in practice */
DateTime actualTimeWhenStoring = startOfDay.plusHours(HOUR_TO_TEST);
int hourOfDay = actualTimeWhenStoring.getHourOfDay();
int hourOffset = startOfDay.plusHours(hourOfDay).getHourOfDay();
System.out.println("Hour of day:" + hourOfDay);
System.out.println("Offset hour:" + hourOffset);
int timeToSave = hourOfDay;
if (hourOffset != hourOfDay) {
timeToSave = (hourOfDay + (hourOfDay - hourOffset));
}
System.out.println("Time to save:" + timeToSave);
/* When obtaining from db: */
DateTime recalculatedTime = startOfDay.plusHours(timeToSave);
System.out.println("Hour of time 'read' from db:" + recalculatedTime.getHourOfDay());
}
}
...or basicly something like that. I'd write a test for it if you choose for going down this route. You can change the HOUR_TO_TEST to see that it moves passed the daylight saving time.
Building on the correct answers by Paweł Dyda & Knubo…
ISO 8601 For String Format
You should never store (serialize) a date-time as a string in the format you mentioned: "30/03/2008 03:00:00". Problems:
Omitted time zone.
Day, Month, Year order is ambiguous.
Should have been translated to UTC time.
If you must serialize a date-time value to text, use a reliable format. The obvious choice is the ISO 8601 standard format. Even better is converting the local time to UTC (Zulu) time zone and then out to ISO 8601 format. Like this: 2013-11-01T04:48:53.044Z
No Midnight
The midnight methods in Joda-Time are deprecated in favor of the Joda-Time method withTimeAtStartOfDay() (see doc). Some days do not have a midnight.
Example Code in Joda-Time 2.3
Some comments about this source code:
// © 2013 Basil Bourque. This source code may be used freely forevery by anyone taking full responsibility for doing so.
// Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
// http://www.joda.org/joda-time/
// Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
// JSR 310 was inspired by Joda-Time but is not directly based on it.
// http://jcp.org/en/jsr/detail?id=310
// By default, Joda-Time produces strings in the standard ISO 8601 format.
// https://en.wikipedia.org/wiki/ISO_8601
Example showing 23 hours in the day of DST (Daylight Saving Time) in Rome Italy, while the day after has 24 hours. Note that the time zone (for Rome) is specified.
// Time Zone list: http://joda-time.sourceforge.net/timezones.html
org.joda.time.DateTimeZone romeTimeZone = org.joda.time.DateTimeZone.forID("Europe/Rome");
org.joda.time.DateTime dayOfDstChange = new org.joda.time.DateTime( 2008, 3, 30, 0, 0, romeTimeZone ) ; // Day when DST
org.joda.time.DateTime dayAfter = dayOfDstChange.plusDays(1);
// How many hours in this day? Should be 23 rather than 24 on day of Daylight Saving Time "springing ahead" to lose one hour.
org.joda.time.Hours hoursObjectForDay = org.joda.time.Hours.hoursBetween(dayOfDstChange.withTimeAtStartOfDay(), dayAfter.withTimeAtStartOfDay());
System.out.println( "Expect 23 hours, got: " + hoursObjectForDay.getHours() ); // Extract an int from object.
// What time is 3 hours after midnight on day of DST change?
org.joda.time.DateTime threeHoursAfterMidnightOnDayOfDst = dayOfDstChange.withTimeAtStartOfDay().plusHours(3);
System.out.println( "Expect 4 AM (04:00) for threeHoursAfterMidnightOnDayOfDst: " + threeHoursAfterMidnightOnDayOfDst );
// What time is 3 hours after midnight on day _after_ DST change?
org.joda.time.DateTime threeHoursAfterMidnightOnDayAfterDst = dayAfter.withTimeAtStartOfDay().plusHours(3);
System.out.println( "Expect 3 AM (03:00) for threeHoursAfterMidnightOnDayAfterDst: " + threeHoursAfterMidnightOnDayAfterDst );
Example of storing a date-time by first translating to UTC. Then upon restoring the date-time object, adjust to the desired time zone.
// Serialize DateTime object to text.
org.joda.time.DateTimeZone romeTimeZone = org.joda.time.DateTimeZone.forID("Europe/Rome");
org.joda.time.DateTime dayOfDstChangeAtThreeHoursAfterMidnight = new org.joda.time.DateTime( 2008, 3, 30, 0, 0, romeTimeZone ).withTimeAtStartOfDay().plusHours(3);
System.out.println("dayOfDstChangeAtThreeHoursAfterMidnight: " + dayOfDstChangeAtThreeHoursAfterMidnight);
// Usually best to first change to UTC (Zulu) time when serializing.
String dateTimeSerialized = dayOfDstChangeAtThreeHoursAfterMidnight.toDateTime( org.joda.time.DateTimeZone.UTC ).toString();
System.out.println( "dateTimeBeingSerialized: " + dateTimeSerialized );
// Restore
org.joda.time.DateTime restoredDateTime = org.joda.time.DateTime.parse( dateTimeSerialized );
System.out.println( "restoredDateTime: " + restoredDateTime );
// Adjust to Rome Italy time zone.
org.joda.time.DateTime restoredDateTimeAdjustedToRomeItaly = restoredDateTime.toDateTime(romeTimeZone);
System.out.println( "restoredDateTimeAdjustedToRomeItaly: " + restoredDateTimeAdjustedToRomeItaly );
When run:
dayOfDstChangeAtThreeHoursAfterMidnight: 2008-03-30T04:00:00.000+02:00
dateTimeBeingSerialized: 2008-03-30T02:00:00.000Z
restoredDateTime: 2008-03-30T02:00:00.000Z
restoredDateTimeAdjustedToRomeItaly: 2008-03-30T04:00:00.000+02:00

Difference in Days between two Java dates?

I want to get the difference between two Java Date objects. I've used Joda-Time library. But the problem is that I'm getting the Days greater difference than that of actual day difference.
Here's my code snippet:
DateFormat formatter = new SimpleDateFormat("mm/dd/yyyy");
Date someDate=new Date();
Date today = Calendar.getInstance().getTime();
try {
someDate = formatter.parse("06/22/2010");
}
catch(ParseException pe) {
System.out.println("Parser Exception");
}
int days = Days.daysBetween(new DateTime(someDate), new DateTime(today)).getDays();
System.out.println(" Days Between " + someDate + " : " + today + " - " + days);
Here's my output:
Days Between Fri Jan 22 00:06:00 IST 2010 : Sun Jul 25 19:27:01 IST 2010 - 184
Here, Why does it takes "06/22/2010" as Jan 22? Does anyone face similar problem?
Help me friends.. Thanx in advance..
It seems like mm refers to minutes, not months, which is MM. Please check here to see the list of appropriate lettering :)
Month is MM
In your case:
DateFormat formatter = new
SimpleDateFormat("MM/dd/yyyy");
Your pattern is slightly defective. mm is parsed as minutes in hour, you're looking for MM which is month of year.
mm => minutes, not months - you need MM for months - that'll resolve your Jan problem!
The other answers correctly solved your specific problem.
LocalDate
But there is a larger solution. If you are starting with only dates, no time-of-day and no time zones, then you should be using the LocalDate class rather than DateTime.
Time Zone
Your code ignores the crucial issue of time zones. Time zones matter even for LocalDate, when trying to determine "today". Do you want today's date in Montréal or in Paris. A new day dawns in Paris earlier. When you omit time zone, you get the JVM’s current default time zone.
Joda-Time Can Parse
Furthermore, let Joda-Time do the parsing. No need to be using java.util.Date & .Calendar at all. Joda-time's formatting characters are almost the same as java.util.Date but not entirely so be sire to consult the doc. In this case it it identical.
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MM/dd/yyyy" );
LocalDate past = formatter.parseLocalDate( "06/22/2010" );
DateTimeZone = DateTimeZone.forID( "America/Montreal" ): // match time zone intended for that input string.
int days = Days.daysBetween( past, LocalDate.now( timeZone ) );

Categories

Resources