How to subtract X days from a date using Java calendar? - java

Anyone know a simple way using Java calendar to subtract X days from a date?
I have not been able to find any function which allows me to directly subtract X days from a date in Java. Can someone point me to the right direction?

Taken from the docs here:
Adds or subtracts the specified amount of time to the given calendar field, based on the calendar's rules. For example, to subtract 5 days from the current time of the calendar, you can achieve it by calling:
Calendar calendar = Calendar.getInstance(); // this would default to now
calendar.add(Calendar.DAY_OF_MONTH, -5).

You could use the add method and pass it a negative number. However, you could also write a simpler method that doesn't use the Calendar class such as the following
public static void addDays(Date d, int days)
{
d.setTime( d.getTime() + (long)days*1000*60*60*24 );
}
This gets the timestamp value of the date (milliseconds since the epoch) and adds the proper number of milliseconds. You could pass a negative integer for the days parameter to do subtraction. This would be simpler than the "proper" calendar solution:
public static void addDays(Date d, int days)
{
Calendar c = Calendar.getInstance();
c.setTime(d);
c.add(Calendar.DATE, days);
d.setTime( c.getTime().getTime() );
}
Note that both of these solutions change the Date object passed as a parameter rather than returning a completely new Date. Either function could be easily changed to do it the other way if desired.

Anson's answer will work fine for the simple case, but if you're going to do any more complex date calculations I'd recommend checking out Joda Time. It will make your life much easier.
FYI in Joda Time you could do
DateTime dt = new DateTime();
DateTime fiveDaysEarlier = dt.minusDays(5);

tl;dr
LocalDate.now().minusDays( 10 )
Better to specify time zone.
LocalDate.now( ZoneId.of( "America/Montreal" ) ).minusDays( 10 )
Details
The old date-time classes bundled with early versions of Java, such as java.util.Date/.Calendar, have proven to be troublesome, confusing, and flawed. Avoid them.
java.time
Java 8 and later supplants those old classes with the new java.time framework. See Tutorial. Defined by JSR 310, inspired by Joda-Time, and extended by theThreeTen-Extra project. The ThreeTen-Backport project back-ports the classes to Java 6 & 7; the ThreeTenABP project to Android.
The Question is vague, not clear if it asks for a date-only or a date-time.
LocalDate
For a date-only, without time-of-day, use the LocalDate class. Note that a time zone in crucial in determining a date such as "today".
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate tenDaysAgo = today.minusDays( 10 );
ZonedDateTime
If you meant a date-time, then use the Instant class to get a moment on the timeline in UTC. From there, adjust to a time zone to get a ZonedDateTime object.
Instant now = Instant.now(); // UTC.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
ZonedDateTime tenDaysAgo = zdt.minusDays( 10 );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

int x = -1;
Calendar cal = ...;
cal.add(Calendar.DATE, x);
See java.util.Calendar#add(int,int)

Instead of writing my own addDays as suggested by Eli, I would prefer to use DateUtils from Apache. It is handy especially when you have to use it multiple places in your project.
The API says:
addDays(Date date, int amount)
Adds a number of days to a date returning a new object.
Note that it returns a new Date object and does not make changes to the previous one itself.

I faced the same challenge where I needed to go back by 1 day (should be able to roll back by one even if previous day falls into previous year or months).
I did following, basically subtracted by 24 hours for 1 day.
someDateInGregorianCalendar.add(Calendar.HOUR, -24);
Alternatively, I could also do
GregorianCalendar cal = new GregorianCalendar();
cal.set(Calendar.YEAR, 2021);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DATE, 1);
System.out.println("Original: " + cal.getTime());
cal.add(Calendar.DATE, -1);
System.out.println("After adding DATE: " + cal.getTime());
OUTPUT:
Original: Fri Jan 01 15:08:33 CET 2021
After adding DATE: Thu Dec 31 15:08:33 CET 2020

It can be done easily by the following
Calendar calendar = Calendar.getInstance();
// from current time
long curTimeInMills = new Date().getTime();
long timeInMills = curTimeInMills - 5 * (24*60*60*1000); // `enter code here`subtract like 5 days
calendar.setTimeInMillis(timeInMills);
System.out.println(calendar.getTime());
// from specific time like (08 05 2015)
calendar.set(Calendar.DAY_OF_MONTH, 8);
calendar.set(Calendar.MONTH, (5-1));
calendar.set(Calendar.YEAR, 2015);
timeInMills = calendar.getTimeInMillis() - 5 * (24*60*60*1000);
calendar.setTimeInMillis(timeInMills);
System.out.println(calendar.getTime());

I believe a clean and nice way to perform subtraction or addition of any time unit (months, days, hours, minutes, seconds, ...) can be achieved using the java.time.Instant class.
Example for subtracting 5 days from the current time and getting the result as Date:
new Date(Instant.now().minus(5, ChronoUnit.DAYS).toEpochMilli());
Another example for subtracting 1 hour and adding 15 minutes:
Date.from(Instant.now().minus(Duration.ofHours(1)).plus(Duration.ofMinutes(15)));
If you need more accuracy, Instance measures up to nanoseconds. Methods manipulating nanosecond part:
minusNano()
plusNano()
getNano()
Also, keep in mind, that Date is not as accurate as Instant. My advice is to stay within the Instant class, when possible.

Someone recommended Joda Time so - I have been using this CalendarDate class http://calendardate.sourceforge.net
It's a somewhat competing project to Joda Time, but much more basic at only 2 classes. It's very handy and worked great for what I needed since I didn't want to use a package bigger than my project. Unlike the Java counterparts, its smallest unit is the day so it is really a date (not having it down to milliseconds or something). Once you create the date, all you do to subtract is something like myDay.addDays(-5) to go back 5 days. You can use it to find the day of the week and things like that.
Another example:
CalendarDate someDay = new CalendarDate(2011, 10, 27);
CalendarDate someLaterDay = today.addDays(77);
And:
//print 4 previous days of the week and today
String dayLabel = "";
CalendarDate today = new CalendarDate(TimeZone.getDefault());
CalendarDateFormat cdf = new CalendarDateFormat("EEE");//day of the week like "Mon"
CalendarDate currDay = today.addDays(-4);
while(!currDay.isAfter(today)) {
dayLabel = cdf.format(currDay);
if (currDay.equals(today))
dayLabel = "Today";//print "Today" instead of the weekday name
System.out.println(dayLabel);
currDay = currDay.addDays(1);//go to next day
}

Eli Courtwright second solution is wrong, it should be:
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DATE, -days);
date.setTime(c.getTime().getTime());

Related

How come Java's Calendar date resets the hour to another value when I convert it to a Date?

I was looking to do a simple script of setting a time every 10minutes on Oct 26th 2020.
My loop looks like below.
However even though the time generally seems right when i output 'time' var, then i convert it to Date object and do a toString() on that 'd' variable then it seems to convert it to another time. If you want to see it run on an online java compiler you can see it in action here:
https://ideone.com/T8anod
You can see it do strange stuff like:
0:00 AM
Mon Oct 26 10:00:00 GMT 2020
0:10 AM
Mon Oct 26 10:10:00 GMT 2020
...
12:00 PM
Mon Oct 26 22:00:00 GMT 2020
12:10 PM
...
Mon Oct 26 22:10:00 GMT 2020
One unusually thing is i'll set a breakpoint in my IDE at 12 hours... and if I debug slowly it will set the correct time. Then i'll remove my breakpoint and play through the rest of the script and the times then end up incorrect again. Very unusual behavior I haven't seen in Java yet.
I could do something like this to reset the hours (or use a different technique):
Date d = cal.getTime();
d.setHours(hour); //deprecated
But I'd rather just figure out for now why Java is acting this way.
for(int hour=0; hour < 24; hour++ ) {
for(int minute = 0; minute < 6; minute++) {
String str_min = minute==0 ? "00" : String.valueOf(minute*10);
String time = String.valueOf( hour > 12 ? hour-12 : hour) +":"+ str_min +" "+ ((hour >= 12 ? Calendar.PM : Calendar.AM)==1 ? "PM" : "AM");
//note: got lazy and not outputting "00" for hour
System.out.println( time );
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, 9); //Oct=9
cal.set(Calendar.DAY_OF_MONTH, 26);
cal.set(Calendar.YEAR, 2020);
cal.set(Calendar.HOUR_OF_DAY, hour );
cal.set(Calendar.MINUTE, minute*10 ); //0=0, 1=10, ... 5=50
cal.set(Calendar.AM_PM, (hour >= 12 ? Calendar.PM : Calendar.AM) );
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date d = cal.getTime();
System.out.println( d.toString() );
}
}
java.util.Date is a lie. It does not represent a date; it represents an instant in time, it has no idea about timezones, or this concept of 'hours'. That's why everything (except the epoch-millis-based methods and constructors) are marked deprecated.
The calendar API tries to fix this, but is a horrible, horrible API.
Use java.time instead. The ugly API goes away, and unlike the old stuff, you have types that actually represent exactly what you want. Given that you aren't messing with timezones here, you want LocalDateTime:
for (int hour = 0; hour < 24; hour++) {
for (int minute = 0; minute < 60; minute += 10) {
LocalDateTime ldt = LocalDateTime.of(2020, 10, 26, hour, minute, 0);
System.out.println(ldt);
// or better:
System.out.println(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(ldt));
}
}
Note how October is '10' in this API, because this API is not insane, for example. You can use any of the many predefined formatters in DTF, or write your own with a pattern to control precisely how you want to render the date.
If you want to represent other things, you can do so; ZonedDateTime for a specific time the way humans would say it (say: I have an appointment with the dentist, who is in Rome, at a quarter past 2 in the afternoon on november 2nd, 2020). The point of such a concept is this: If Rome decides to switch timezones, then the actual instant in time your appointment occurs should change along with it.
If you want an instant in time, there's Instant. This is a specific moment in time (in the past or future) that will not change in terms of how many milliseconds remain until it occurs. Even in the face of countries changing their zone.
And LDT is, well, LDT: It just represents a year, a month, a day, hours, minutes, and seconds - without a timezone.
tl;dr
LocalDate
.now( ZoneId.of( "America/Chicago" ) ) // Today
.atStartOfDay( ZoneId.of( "America/Chicago" ) ) // First moment of today. Returns a `ZonedDateTime` object.
.plus(
Duration.ofMinutes( 10 ) // Ten minutes later.
) // Returns another `ZonedDateTime` object.
Avoid legacy date-time classes
You are using terrible date-time classes that were supplanted years ago by the java.time classes. Sun, Oracle, and the JCP gave up on those classes, and so should you.
Rather than try to understand those awful classes, I suggest you invest your effort in learning java.time.
Use java.time
Much easier to capture a Instant object when you want the current date-time moment.
Note that java.time uses immutable objects. Rather than alter an existing object, we generate a fresh one.
To represent a moment for every ten-minute interval of today:
ZoneId z = ZoneId.of( "Africa/Tunis" ) ; // Or "America/New_York", etc.
LocalDate today = LocalDate.now( z ) ;
Your code makes incorrect assumptions. Days or not always 24 hours long. They may be 23 hours, 25 hours, or some other length. Also not every day in every time zone starts at 00:00. Let java.time determine the first moment of the day.
ZonedDateTime start = today.atStartOfDay( z ) ;
Get the start of the next day.
ZonedDateTime stop = start.plusDays( 1 ) ;
Loop for your 10-minute chunk of time. Represent that chunk as a Duration.
Duration d = Duration.ofMinutes( 10 ) ;
List< ZonedDateTime > results = new ArrayList<>() ;
ZonedDateTime zdt = start ;
while( zdt.isBefore( stop ) )
{
results.add( zdt ) ;
zdt = zdt.plus( d ) ;
}
See this code run live at IdeOne.com.
Strings
You can generate strings in any format to represent the content of those ZonedDateTime objects. You can even let java.time automatically localize.
Locale locale = Locale.CANADA_FRENCH ; // Or Locale.US etc.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale ) ;
String output = myZonedDateTime.format( f ) ;
In particular, Locale.US and FormatStyle.MEDIUM might work for you. Fork the code at IdeOne.com to experiment.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 brought some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
The other answers tell you to use a different API, i.e. to not use Calendar, and they are right, but they don't tell you why the question code doesn't work.
If you read the documentation of Calendar, and look for section "Calendar Fields Resolution", you will find (bold highlight by me):
Calendar Fields Resolution
When computing a date and time from the calendar fields, there may be insufficient information for the computation (such as only year and month with no day of month), or there may be inconsistent information (such as Tuesday, July 15, 1996 (Gregorian) -- July 15, 1996 is actually a Monday). Calendar will resolve calendar field values to determine the date and time in the following way.
If there is any conflict in calendar field values, Calendar gives priorities to calendar fields that have been set more recently. The following are the default combinations of the calendar fields. The most recent combination, as determined by the most recently set single field, will be used.
For the date fields:
YEAR + MONTH + DAY_OF_MONTH
YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
YEAR + DAY_OF_YEAR
YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
For the time of day fields:
HOUR_OF_DAY
AM_PM + HOUR
The question code has:
cal.set(Calendar.HOUR_OF_DAY, hour );
cal.set(Calendar.AM_PM, (hour >= 12 ? Calendar.PM : Calendar.AM) );
Since the last of those fields set is AM_PM, it resolved the hour using AM_PM + HOUR, and since you never call clear() and never set HOUR, the value is the 12-hour clock value set by the getInstance() call, i.e. the current time.
You have 2 choices to fix this:
// Only set the 24-hour value
cal.set(Calendar.HOUR_OF_DAY, hour);
// Set the 12-hour value
cal.set(Calendar.HOUR, hour % 12);
cal.set(Calendar.AM_PM, (hour >= 12 ? Calendar.PM : Calendar.AM) );
I would recommend doing the first one.
I would also highly recommend calling clear() before setting fields, so the result is not polluted by left-over values. That would eliminate the need to set SECOND and MILLISECOND to 0.
Actually, I would recommend using the newer Time API, like the other answers do, but at least you now know why the code was failing.

Getting a Date from a GregorianCalendar

The GregorianCalendar is being inconsistent:
Calendar cal = new GregorianCalendar(2000, 0, 1);
long testCalOne = cal.getTimeInMillis();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
long testCalTwo = cal.getTimeInMillis();
Calendar cal2 = new GregorianCalendar(2000, 0, 1);
cal2.setTimeZone(TimeZone.getTimeZone("UTC"));
long testCalThree = cal2.getTimeInMillis();
System.out.println(testCalOne + ", " + testCalTwo + ", " + testCalThree);
Results in
946681200000, 946681200000, 946684800000
This represents 2000-01-01 midnight in GMT+1, GMT+1 and UTC respectively. My timezone is +1 hour relative to UTC.
The problem here is that the getTimeInMillis is supposed to return the amount of milliseconds since 1970-01-01 in UTC. Only testCalThree is correct.
Another problem is that setTimeZone is seemingly not working depending on whether I called getTimeInMillis before.
My goal is to take a Calendar I receive as parameter from other code and get a UTC (java.util) Date for further use.
tl;dr
myGregCal.toZonedDateTime()
.toInstant()
…or…
java.util.Date.from(
myGregCal.toZonedDateTime()
.toInstant()
)
java.time
My goal is to take a Calendar I receive as parameter from other code and get a UTC (java.util) Date for further use.
The troublesome old date-time classes of Calendar and Date are now legacy, supplanted by the java.time classes. Fortunately you can convert to/from java.time by calling new methods on the old classes.
ZonedDateTime zdt = myGregCal.toZonedDateTime() ;
For UTC value, extract an Instant. That class represents a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = zdt.toInstant() ;
To generate a String representing that UTC value in a standard ISO 8601 format, call toString.
String output = instant.toString() ;
If you need other formats in generated strings, convert to the more flexible OffsetDateTime and use DateTimeFormatter. Search Stack Overflow for many examples.
Best to avoid the Date class. But if you must, convert. Like Instant, Date represents a point on the timeline in UTC. But Date is limited to milliseconds resolution. So you risk data loss, lopping off digits from the decimal fraction of a second beyond the 3 digits of milliseconds versus 9 digits of nanoseconds.
java.util.Date utilDate = Date.from( instant ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I think it's a bug in the Calendar implementation. time is cached, i.e. if you've calculated it once it is reused unless something changes.
But somehow setting time zone is not recognized as a relevant change.
You can force re-calculation of time in ms by changing or clearing some field explicitly. So this:
Calendar cal = new GregorianCalendar(2000, 0, 1);
long testCalOne = cal.getTimeInMillis();
cal.clear(Calendar.ZONE_OFFSET);
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
long testCalTwo = cal.getTimeInMillis();
Calendar cal2 = new GregorianCalendar(2000, 0, 1);
cal2.setTimeZone(TimeZone.getTimeZone("UTC"));
long testCalThree = cal2.getTimeInMillis();
System.out.println(testCalOne + ", " + testCalTwo + ", " + testCalThree);
Gives:
946681200000, 946684800000, 946684800000
As you would expect. The only thing I had to do is cal.clear(Calendar.ZONE_OFFSET) before setting time zone.
Anyway, I'd like to repeat the recommendation from comments. If you value your sanity, switch to JodaTime or Java8 date/time.
Upon thinking further on it, the code may work as intended. setTimeZone may just function differently depending on whether a getter has been called upon the Calendar or not.
In the first case, it changes the timezone, but because the time has already been gotten and therefore initialized, the UTC time is unchanged.
In the second case, it indicates that the initializing date of 2001-1-1 we passed in the constructor was a UTC time and should be parsed as UTC rather than the local timezone.
If so, then the results make sense.

Best Way to Set Day to the First of the Month Using DateTime Without Inherent WithDayOfMonth Method

So, I'm trying to basically take 2 DateTime objects and set them to the first day of their respective months so that I can ultimately calculate the months between the two dates.
Example of the code:
DateTime dt = new DateTime();
DateTime newDT = dt.withDayOfMonth(1);
And before anyone asks, the actual code coverts a Date object into a DateTime object which is used in another section of the code.
The issue is, when I do this in a unit test it seems to work just fine. However, when I try to test this using SOAP UI I can see in the course of debugging that I'm getting a runtime exception due to:
method lookup failed for selector "withDayOfMonth" with signature "(I)Lorg/joda/time/DateTime;"
In the corresponding server.txt log file, I can see a stack trace which indicates a no such method has occured.
After further research, I've found that our app server currently employs an outdated version of the JodaTime jar (1.2.1), while my eclipse library contains the correct jar (1.6.2).
However, now the question becomes what's the best way to accomplish my goal here (to create a new DateTime object with the first day of the month set to 0) since I don't have access to the withDayOfMonth method provided by JodaTime?
tl;dr
LocalDate firstOfThisMonth =
LocalDate.now( ZoneId.of( "America/Montreal" ) )
.with( TemporalAdjusters.firstDayOfMonth() ) ;
Details
Other answers address your Joda-Time question. However, the Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. So here is a solution in java.time code.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
TemporalAdjuster
The TemporalAdjuster interface in java.time provides for classes to manipulate a value. The TemporalAdjusters class (note the plural s) provides several handy implementations of adjusters. One is firstDayOfMonth.
LocalDate firstOfThisMonth = today.with( TemporalAdjusters.firstDayOfMonth() ) ;
firstOfThisMonth.toString(): 2016-03-01
Period
The Period class tracks a span of time not attached to the timeline. It keeps a number of years, months, and days.
LocalDate start = LocalDate.of ( 2016 , 1 , 1 ) ;
LocalDate stop = LocalDate.of ( 2016 , 3 , 1 ) ;
Period p = Period.between ( start , stop ) ;
Calling toString on a Period generates a string in standard ISO 8601 format.
P2M
You can ask for one part as a number, such as number of months.
int months = p.getMonths();
2
Note that the elapsed time shown here wisely uses the Half-Open approach where the beginning is inclusive while the ending is exclusive.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
A possible way to do so, using another method for Joda-Time API which is present in 1.2.1 version it's the follow:
DateTime dateTime = new DateTime().dayOfMonth().withMinimumValue();
Another approach could be to use jdk Calendar to set the first day of the month for a date. And then get the joda DateTime using DateTime(Calendar cal) constructor:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, 1);
DateTime dateTime = new DateTime(cal);
However probably as other answer suggest the best you can do is update your Joda-Time version.
Calculate months from difference of the two month values. For example if newDate is 1st July 2016 and oldDate is 31st May 2016, newDate.getMonth() will return 7 and oldDate.getMonth() will return 5, and the difference will be rounded up as required.
int months = newDate.getMonth() - oldDate.getMonth(); // 7 - 5 = 2

Number of days between two dates (excluding these two dates)

I searched for this is SO there are so many post asking this question but all the answers is difference In Milliseconds / (24* 1000 * 60 * 60) that gives the number of 24 Hrs between two dates .
but i need the number of days between 2 dates.
I.e. if date1 is 09/09/13 09:00 and date2 is 10/09/13 22:00 I need the difference as 0 and not 1 because date1 and date2 are consecutive days (even if there is more than 24 hour gap between them).
Note: I know the removing the time part and using the difference In Milliseconds / (24* 1000 * 60 * 60) method. I am looking for a better solution.
update: the app is first used on 09/09/13 09:00 its a Wednesday then the app was used on 10/09/13 22:00` its Thursday. now the user has used the app both Wednesday and Thursday even though there is more than 24 hour gap. now if i calculate the number of 24 hours between the 2 dates it gives one. as there is a day gap between 2 dates. i need it to give zero as the user used it Wednesday and Thursday there is NO DAY BETWEEN WEDNESDAY AND THURSDAY.
hope you understood my question. if you still didn't just leave it, i tried by best explaining.
Here's a simple solution:
Calendar calendar = Calendar.getInstance();
calendar.setTime(startDate);
while(calendar.getTime().before(endDate))
{
noOfDays++;
calendar.add(Calendar.DAY_OF_MONTH,1);
}
Where startDate and endDate are instances of the Date class.
Note: You need to initialize the date objects so that they have the same time but only differ in their dates. Setting them both to 12 AM should do the trick:
date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.text.SimpleDateFormat;
import java.text.ParseException;
public class test {
public static void main(String[] args) throws ParseException {
String dateStart = "09/09/13 09:00";
String dateStop = "10/09/13 22:00";
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");
Date date1 = format.parse(dateStart);
Date date2 = format.parse(dateStop);
// calculate difference in milliseconds
long diff = (date2.getTime() - date1.getTime()) - 86400000;
diff = (diff <= 0 ? 0 : diff);
System.out.println(TimeUnit.MILLISECONDS.toDays(diff));
}
}
This will give the difference between 2 dates. And subtract a day (if its negative, it sets the difference to 0 day). This will work as long as dateStop is greater than dateStart, otherwise it will just print 0;
I have avoided using Joda Time for ages, but this past week I got round to using it for exactly this issue. And it was well worth it!
It is very easy to introduce some strange date handling bugs when dealing with plain Java - for example what happens when daylight savings time changes. Joda Time builds all these exceptions in already.
Check related question here:
Number of days between two dates in Joda-Time
Update
As of Java 8, the time & date functionality has been improved, and the Joda Time team suggests using that instead of their library. Here's what they say on the landing page:
Note that from Java SE 8 onwards, users are asked to migrate to
java.time (JSR-310) - a core part of the JDK which replaces this
project.
Thanks to Basil Bourque for the comment.
You can use this trick: if date1 is before date2 you can set hour in date1 to 1 and in date2 to 0. This way hour part in entire time difference will never be greater than 24h, so will not affect calculations so only days/months/years will matter.
Here is code example
public static long daysBetween(Date date1, Date date2) {
Calendar c1 = Calendar.getInstance();
c1.setTime(date1);
Calendar c2 = Calendar.getInstance();
c2.setTime(date2);
if (date1.before(date2)) {
c1.set(Calendar.HOUR_OF_DAY, 1);
c2.set(Calendar.HOUR_OF_DAY, 0);
} else {
c2.set(Calendar.HOUR_OF_DAY, 1);
c1.set(Calendar.HOUR_OF_DAY, 0);
}
return (c2.getTimeInMillis() - c1.getTimeInMillis())
/ (24 * 60 * 60 * 1000);
}
//DEMO
public static void main(String[] args) throws Exception {
DateFormat df = new SimpleDateFormat("dd/MM/yy hh:mm");
Date date1 = df.parse("09/09/13 09:00");
Date date2 = df.parse("11/09/13 22:00");
System.out.println(daysBetween(date1, date2));
}
Output: 1
For dates 11/09/13 09:00 09/09/13 22:00 result will be -1 since date1 is after date2
tl;dr
ChronoUnit.DAYS.between(
earlierInstant.atZone( ZoneId.of( "Africa/Tunis" ) ).toLocalDate() ,
Instant.now().atZone( ZoneId.of( "Africa/Tunis" ) ).toLocalDate()
)
java.time
The modern approach uses the java.time classes that supplanted the troublesome old date-time classes such as Date & Calendar.
If you want to calculate the number of elapsed days as the number of calendar dates rather than the number of 24-hour chunks of time, use a date-only class rather than a date-time class.
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
Generally best to think, work, log, serialize, and exchange values in UTC. For that, use Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant earlier = Instant.now() ;
…
Instant later = Instant.now() ;
Serialize to text in standard ISO 8601 format by calling Instant::toString and Instant::parse.
To get your elapsed dates, apply a time zone (ZoneId) to get ZonedDateTime objects.
ZonedDateTime zdtEarlier = earlier.atZone( z ) ;
ZonedDateTime zdtLater = later.atZone( z ) ;
Extract the date-only values.
LocalDate ldEarlier = zdtEarlier.toLocalDate() ;
LocalDate ldLater = zdtLater.toLocalDate() ;
Now we can get the elapsed days between the dates.
long daysElapsed = ChronoUnit.DAYS.between( ldEarlier , ldLater ) ;
This calculation is done per the Half-Open approach where the beginning is inclusive while the ending is exclusive. So, for example, a month starts with the first day of the month and runs up to, but does not include, the first day of the following month. Using this approach consistently throughout your business logic, database queries, and so on will make your codebase less error-prone and easier to read/debug/maintain.
I understand you want to use a fully-Open approach where both beginning and ending is exclusive. I strongly suggest you reconsider that position. But if you insist, simply subtract 1 from our calculation above.
long daysElapsedFullyOpen = ( ChronoUnit.DAYS.between( ldEarlier , ldLater ) - 1 ) ; // Subtract 1 to get a fully-Open answer. NOT recommended.
By the way, you may want to consider the Period class in your work. Similarly, you may find useful the LocalDateRange class found in the ThreeTen-Extra project.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Java Timestamp - Adding five minutes

looking for some help with a bit of Java code i'm working on, i have the following code which prints out the date and time:
Date dNow = new Date( ); // Instantiate a Date object
SimpleDateFormat ft = new SimpleDateFormat ("MMM d, yyyy k:mm:ss"); // Time at server
Result: Mar 15, 2013 10:19:48
I'm creating a javascript counter to work from this number and countdown from 5 minutes. So i need to add 5 minues to the current date time in Java.
So, if the current date time is: Mar 15, 2013 10:19:48
I need to add 5 minutes to Java so that it prints out: Mar 15, 2013 10:24:48
Any ideas?
Instead of starting with
new Date()
start with
new Date(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5))
This will give you a Date instance that represents your required point in time. You don't need to change any other part of your code.
Ignoring Dates and focusing on the question.
My preference is to use java.util.concurrent.TimeUnit since it adds clarity to my code.
In Java,
long now = System.currentTimeMillis();
5 minutes from now using TimeUtil is:
long nowPlus5Minutes = now + TimeUnit.MINUTES.toMillis(5);
Reference: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/TimeUnit.html
You should use Calendar class to manipulate Date and time:
The Calendar class is an abstract class that provides methods for
converting between a specific instant in time and a set of calendar
fields such as YEAR, MONTH, DAY_OF_MONTH, HOUR, and so on, and for
manipulating the calendar fields, such as getting the date of the next
week
Date dNow = new Date( ); // Instantiate a Date object
Calendar cal = Calendar.getInstance();
cal.setTime(dNow);
cal.add(Calendar.MINUTE, 5);
dNow = cal.getTime();
tl;dr
Instant.now()
.plusSeconds( TimeUnit.MINUTES.toSeconds( 5 ) )
.toString()
2017-01-23T03:11:53.763Z
Details
The other Answers are outdated as of Java 8. The troublesome old date-time classes are now legacy, supplanted by the java.time classes.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now();
This class can do math such as adding a number of seconds. We can use the TimeUnit enum to covert our desired five minutes into a number of seconds.
long seconds = TimeUnit.MINUTES.toSeconds( 5 );
Instant fiveMinutesLater = instant.plusSeconds( seconds );
To generate a string in standard ISO 8601 format, call toString.
String output = fiveMinutesLater.toString();
To generate strings in other formats, use the ZonedDateTime class and DateTimeFormatter class. Search Stack Overflow for many examples and discussions of those classes.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Use this ...
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getTime());
calendar.add(Calendar.MINUTE, 5);
System.out.println(calendar.getTime());
Date dNow = new Date(System.currentTimeMillis()+5*60*1000)
SimpleDateFormat ft = new SimpleDateFormat ("MMM d, yyyy k:mm:ss");
System.out.println(ft.format(dNow));
with the help of deprecated method getMinutes(),setMinutes(int)
Date dNow = new Date( ); // Instantiate a Date object
int mm = dNow.getMinutes();
dNow.setMinutes(mm+5);
Java dates use Unix time in milliseconds. So you either calculate how much 5 minutes are in milliseconds and add them to your date or use the Calendar class which does it for you.
You can try this one best performance
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(System.currentTimeMillis());
gc.add(Calendar.MINUTE, -5);
System.out.println(new java.util.Date().getTime());
System.out.println(new java.util.Date(gc.getTime().getTime()).getTime());

Categories

Resources