I have a now time:
new Date();
And I have some hour constants, for example, 23 and 8 (it's 11pm or 23:00, 8am or 08:00).
How I can know is now time between it's two hour constants?
It need to run some code of program or not to run if now time is between in two hours, for example, do not run some code if its already evening and while it is not a morning.
Here the image to better explain:
Some situations when silent mode does not fire:
00:00 20.06.13 - 23:00 20.06.13 // after 23.00 can loud!!
23:00 20.06.13 - 15:00 20.06.13 // after 15.00 can loud!!
01:00 20.06.13 - 08:00 20.06.13 // after 08.00 can loud!!
21:00 20.06.13 - 08:00 20.06.13 // after 08.00 can loud!!
try this
int from = 2300;
int to = 800;
Date date = new Date();
Calendar c = Calendar.getInstance();
c.setTime(date);
int t = c.get(Calendar.HOUR_OF_DAY) * 100 + c.get(Calendar.MINUTE);
boolean isBetween = to > from && t >= from && t <= to || to < from && (t >= from || t <= to);
Calendar cal = Calendar.getInstance(); //Create Calendar-Object
cal.setTime(new Date()); //Set the Calendar to now
int hour = cal.get(Calendar.HOUR_OF_DAY); //Get the hour from the calendar
if(hour <= 23 && hour >= 8) // Check if hour is between 8 am and 11pm
{
// do whatever you want
}
java.time
The modern way is with the java.time classes built into Java 8 and later. Much of the functionality is back-ported to Java 6 & 7 in the ThreeTen-Backport project and further adapted to Android in ThreeTenABP project.
Time zone is crucial here. For any given moment, the date and time-of-day both vary around the world by zone.
ZoneId z = ZoneId.of( "America/Montreal" );
Get your current moment.
ZonedDateTime zdt = ZonedDateTime.now( z );
Extract the time-of-day. The Local part of the name means there is no concept of time zone contained within the object.
LocalTime lt = zdt.toLocalTime();
Define the limits of the evening.
LocalTime start = LocalTime.of( 23 , 0 ); // 11 PM.
LocalTime stop = LocalTime.of( 8 , 0 ); // 8 AM.
Compare.
We need to figure out if we are straddling over a new day or within the same day. A LocalTime has no concept of date, only a single generic day of 24 hours. So we must test if the start is before or after the stop as we need different comparison algorithm for each case. And we should consider if the start equals the stop, as that may be a special case depending on your business rules.
In date-time work, we usually define spans of time as Half-Open, where the beginning is inclusive while the ending is exclusive.
Here's one way to do it.
Boolean silentRunning = null ;
if( start.equals( stop ) ) {
silentRunning = Boolean.FALSE ;
} else if( stop.isAfter( start ) ) { // Example 3 PM to 6 PM.
silentRunning = ( ! lt.isBefore( start ) ) && lt.isBefore( stop ) ;
} else if ( stop.isBefore( start ) ) { // Example 11 PM to 8 AM.
silentRunning = ( lt.equals( start ) || lt.isAfter( start ) ) && lt.isBefore( stop ) ;
} else {
// Error. Should not reach this point. Paranoid check.
}
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….
UPDATE: The above is a later version of this Answer. Below is the old.
Joda-Time
The Joda-Time library is vastly superior to the java.util.Date and .Calendar classes for date-time work.
Time zone is crucial for determine the time of day. Obviously "now" is later in the day in Paris than Montréal.
Definig a range of time is usually best done as half-open, [), where the beginning is inclusive but the ending is exclusive.
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zone );
Integer hour = now.getHourOfDay();
Boolean isNight = ( ( hour >= 23 ) && ( hour < 8 ) );
I think that this is more cleaner solution and it`s works. I have tested it with different time parameters.
/**
* #param fromHour Start Time
* #param toHour Stop Time
* #param now Current Time
* #return true if Current Time is between fromHour and toHour
*/
boolean isTimeBetweenTwoHours(int fromHour, int toHour, Calendar now) {
//Start Time
Calendar from = Calendar.getInstance();
from.set(Calendar.HOUR_OF_DAY, fromHour);
from.set(Calendar.MINUTE, 0);
//Stop Time
Calendar to = Calendar.getInstance();
to.set(Calendar.HOUR_OF_DAY, toHour);
to.set(Calendar.MINUTE, 0);
if(to.before(from)) {
if (now.after(to)) to.add(Calendar.DATE, 1);
else from.add(Calendar.DATE, -1);
}
return now.after(from) && now.before(to);
}
You can see a tutorial here with Date.before and you can do with Date.after
Also you can get his milliseconds and compare it.
here is a function that checks is now(current time) is either between
1 to 4 OR
4 to 8 OR
8 to 12 OR
12 to 16 OR
16 to 20 OR
20 to 1 And returns next accuring time.
private Calendar GetTimeDiff() throws ParseException {
Calendar now = Calendar.getInstance();
Calendar one = Calendar.getInstance();
one.set(Calendar.HOUR_OF_DAY, 1);
one.set(Calendar.MINUTE, 0);
one.set(Calendar.SECOND, 0);
Calendar four = Calendar.getInstance();
four.set(Calendar.HOUR_OF_DAY, 4);
four.set(Calendar.MINUTE, 0);
four.set(Calendar.SECOND, 0);
Calendar eight = Calendar.getInstance();
eight.set(Calendar.HOUR_OF_DAY, 8);
eight.set(Calendar.MINUTE, 0);
eight.set(Calendar.SECOND, 0);
Calendar twelve = Calendar.getInstance();
twelve.set(Calendar.HOUR_OF_DAY, 12);
twelve.set(Calendar.MINUTE, 0);
twelve.set(Calendar.SECOND, 0);
Calendar sixteen = Calendar.getInstance();
sixteen.set(Calendar.HOUR_OF_DAY, 16);
sixteen.set(Calendar.MINUTE, 0);
sixteen.set(Calendar.SECOND, 0);
Calendar twenty = Calendar.getInstance();
twenty.set(Calendar.HOUR_OF_DAY, 20);
twenty.set(Calendar.MINUTE, 0);
twenty.set(Calendar.SECOND, 0);
if(now.getTime().after(one.getTime()) && now.getTime().before(four.getTime())) {
return four;
}
if(now.getTime().after(four.getTime()) && now.getTime().before(eight.getTime())) {
return eight;
}
if(now.getTime().after(eight.getTime()) && now.getTime().before(twelve.getTime())) {
return twelve;
}
if(now.getTime().after(twelve.getTime()) && now.getTime().before(sixteen.getTime())) {
return sixteen;
}
if(now.getTime().after(sixteen.getTime()) && now.getTime().before(twenty.getTime())) {
return twenty;
}
if(now.getTime().after(twenty.getTime()) && now.getTime().before(one.getTime())) {
return one;
}
return now;
}
PHP Solution
I wasn't able to find a solution for this in PHP, but #sytolk answer helped. heres the PHP version.
// $current = Date('H:i:s');
$current = "01:00:00";
$start = "23:00:00";
$end = "02:00:00";
$current = DateTime::createFromFormat('H:i:s', $current);
$start = DateTime::createFromFormat('H:i:s', $start);
$end = DateTime::createFromFormat('H:i:s', $end);
if ($end < $start) {
if ($current > $end) {
$end->modify('+1 day');
} else {
$start->modify('-1 day');
}
}
$inTime = $current > $start && $current < $end;
You could also convert your input string to an integer and compare it against your constants. This way you don't even need to work with the Calendar and Date objects.
public class testDateRange {
static final int START_HOUR = 8;
static final int END_HOUR = 23;
public static void main(String[] args) {
String now_time = new SimpleDateFormat("HH:mm").format(new Date());
System.err.println(isInRange(Integer.parseInt(now_time.replace(":","")),START_HOUR*100,END_HOUR*100));
}
private static boolean isInRange(int now_time, int start_time, int end_time) {
if ((now_time>start_time)&&
(now_time<end_time) )
{
return true;
}
return false;
}
}
Related
I have an ISO String date like this one: 2019-12-17 15:14:29.198Z
I would like to know if this date is in the previous 15 minutes from now.
Is-it possible to do that with SimpleDateFormat ?
val dateIso = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.FRENCH).parse(isoString)
java.time.Instant
Use Instant class to represent a moment in UTC.
To parse, replace SPACE with a T per the ISO 8601 standard.
Instant instant = Instant.parse( "2019-12-17 15:14:29.198Z".replace( " " , "T" ) ;
Determine the current moment in UTC.
Instant now = Instant.now() ;
Determine 15 minutes ago. Call plus…/minus… methods for date-time math.
Instant then = now.minusMinutes( 15 ) ;
Apply your test. Here we use the Half-Open approach where the beginning is inclusive while the ending is exclusive.
boolean isRecent =
( ! instant.isBefore( then ) ) // "Not before" means "Is equal to or later".
&&
instant.isBefore( now )
;
For older Android, add the ThreeTenABP library that wraps the ThreeTen-Backport library. Android 26+ bundles java.time classes.
If you are doing much of this work, add the ThreeTen-Extra library to your project (may not be appropriate for Android, not sure). This gives you the Interval class and it’s handy comparison methods such as contains.
Interval.of( then , now ).contains( instant )
If you already know the reference date everytime you access the program, you can use java.util.Calendar.
boolean isBefore;
long timeToCheck = 15*60*1000; //15 minutes.
Calendar calendar = Calendar.getInstance(), calendar2 = Calendar.getInstance();
calendar.set(Calendar.DATE, yourDay);
calendar.set(Calendar.HOUR_OF_DAY, yourHour);
calendar.set(Calendar.MINUTE, yourMinute);
calendar.set(Calendar.SECOND, yourSecond);
if (calendar.before(calendar2)){
long timeInMillis = calendar2.getTimeInMillis() - calendar.getTimeInMillis();
if ( timeInMillis >= timeToCheck ) isBefore = true;
else isBefore = false;
}
Is this you want:
int xMinutes = 10 * 60 * 1000;
long dateIsoinMillis = dateIso.getTime();
long xMinsAgo = System.currentTimeMillis() - xMinutes;
if (dateIsoinMillis < xMinsAgo) {
System.out.println("searchTimestamp is older than 10 minutes");
}
Been wrestling with this problem for a while, would love some input.
The problem I want to solve collects all of the dates in one specific year which fall on a particular day of the week, for example, every Tuesday in 2014. The dates are stored in an ArrayList<Date>. This list is then returned.
Also have to validate to make sure the year is not 0 and the day of the week submitted must be a number between 1-7.
If there are any issues, I would love to know what I have screwed up.
public List<Date> getDatesforDayOfWeek(int year, int dayOfWeek) throws InvalidDateException, ParseException {
List<Date> dateList = new ArrayList<>();
if (year <= 0 || (1 > dayOfWeek && dayOfWeek > 7)) {
throw new InvalidDateException("Year or day of week is invalid.");
} else {
Calendar newCal = Calendar.getInstance();
newCal.set(YEAR, year);
newCal.set(DAY_OF_YEAR, 1);
while (newCal.get(YEAR) < year + 1) {
int currentDayOfWeek = newCal.get(DAY_OF_WEEK);
Date newDate = null;
if (currentDayOfWeek >= dayOfWeek) {
int dayOfMonth = newCal.get(DAY_OF_MONTH);
String strDayOfMonth = String.valueOf(dayOfMonth);
String strYear = String.valueOf(year);
DateUtility d1 = new DateUtility();
Date passDate = newCal.getTime();
String weekDay = d1.getWeekDayNameAbbreviation(passDate);
String monthAbbreviation = d1.getMonthAbbreviation(passDate);
String finalString = new String();
finalString.concat(weekDay).concat(" ").
concat(monthAbbreviation).concat(" ").
concat(strDayOfMonth).concat(" ").
concat(strYear);
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd YYYY");
Date theDate = format.parse(finalString);
dateList.add(theDate);
}
newCal.add(Calendar.DATE, 1);
}
}
return (dateList);
}
Your question fails to specify which is first day of the week, but things are further complicated by your method for testing the current day of the week. Let's start with validating days of the week by using the Calendar standard,
private static boolean isValidDayOfWeek(int dayOfWeek) {
switch (dayOfWeek) {
// Seven days of the week.
case Calendar.SUNDAY: case Calendar.MONDAY: case Calendar.TUESDAY:
case Calendar.WEDNESDAY: case Calendar.THURSDAY: case Calendar.FRIDAY:
case Calendar.SATURDAY:
return true;
}
return false;
}
It then follows that we can do something like,
public static List<Date> getDatesforDayOfWeek(int year, int dayOfWeek) {
List<Date> dateList = new ArrayList<>();
if (year <= 0 || !isValidDayOfWeek(dayOfWeek)) {
return null;
} else {
Calendar newCal = Calendar.getInstance();
newCal.set(Calendar.YEAR, year);
newCal.set(Calendar.DAY_OF_YEAR, 1);
// First, let's loop until we're at the correct day of the week.
while (newCal.get(Calendar.DAY_OF_WEEK) != dayOfWeek) {
newCal.add(Calendar.DAY_OF_MONTH, 1);
}
// Now, add the Date to the List. Then add a week and loop (stop
// when the year changes).
do {
dateList.add(newCal.getTime());
newCal.add(Calendar.DAY_OF_MONTH, 7);
} while (newCal.get(Calendar.YEAR) == year);
}
return dateList;
}
Leaving us with main(). So, to get every Tuesday in 2014 you could then use -
public static void main(String[] args) {
List<Date> tuesdays = getDatesforDayOfWeek(2014, Calendar.TUESDAY);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
for (Date d : tuesdays) {
System.out.println(df.format(d));
}
}
tl;dr
startOfYear // `Year.of( 2019 ).atDay( 1 )` gets the first day of the year.
.datesUntil( startOfYear.plusYears( 1 ) ) // Generate a stream of incrementing `LocalDate` objects.
.filter( // Pull out the dates that are a Tuesday.
t -> t.getDayOfWeek().equals( DayOfWeek.TUESDAY )
)
.collect( Collectors.toList() ) // Return results in a `List` of `LocalDate` objects.
ISO 8601
The ISO 8601 standard for date-time work defines Monday as the first day of week, identified by number 1. Sunday is 7.
Avoid j.u.Date & .Calendar
The java.util.Date and .Calendar classes bundled with java are notoriously troublesome. Avoid them. They have been supplanted in Java 8 by the new java.time package. That package was inspired by Joda-Time, an alternative that remains an active viable project with some advantages.
Both Joda-Time and java.time use ISO 8601 by default.
Date-Only
For this Question, we need only dates, not time-of-day or time zones. Both Joda-Time and java.time offer a LocalDate class for this purpose.
java.time
Use Year.of and LocalDate::plusYears to determine the bounds of a year, yielding a pair of LocalDate objects for each first-day-of-year.
LocalDate startOfYear = Year.of( 2019 ).atDay( 1 ); // Determine first day of the year.
LocalDate startOfFollowingYear = startOfYear.plusYears( 1 );
Loop, incrementing the date one day at a time. If that date happens to be a Tuesday, add it to our collection.
LocalDate localDate = startOfYear;
List < LocalDate > tuesdays = new ArrayList <>( 55 ); // Set initialCapacity to maximum number of tuesdays in a year. Probably 53, but I'll go with 55 for good measure.
while ( localDate.isBefore( startOfFollowingYear ) )
{
if ( localDate.getDayOfWeek().equals( DayOfWeek.TUESDAY ) )
{
tuesdays.add( localDate );
}
// Set up the next loop.
localDate = localDate.plusDays( 1 );
}
System.out.println( tuesdays );
See this code run live at IdeOne.com.
[2019-01-01, 2019-01-08, 2019-01-15, 2019-01-22, 2019-01-29, 2019-02-05, 2019-02-12, 2019-02-19, 2019-02-26, 2019-03-05, 2019-03-12, 2019-03-19, 2019-03-26, 2019-04-02, 2019-04-09, 2019-04-16, 2019-04-23, 2019-04-30, 2019-05-07, 2019-05-14, 2019-05-21, 2019-05-28, 2019-06-04, 2019-06-11, 2019-06-18, 2019-06-25, 2019-07-02, 2019-07-09, 2019-07-16, 2019-07-23, 2019-07-30, 2019-08-06, 2019-08-13, 2019-08-20, 2019-08-27, 2019-09-03, 2019-09-10, 2019-09-17, 2019-09-24, 2019-10-01, 2019-10-08, 2019-10-15, 2019-10-22, 2019-10-29, 2019-11-05, 2019-11-12, 2019-11-19, 2019-11-26, 2019-12-03, 2019-12-10, 2019-12-17, 2019-12-24, 2019-12-31]
Or get fancy with functional lambda syntax. The LocalDate::datesUntil method generates a stream, in Java 9 and later. Then filter the stream by a match on DayOfWeek.TUESDAY.
LocalDate startOfYear = Year.of( 2019 ).atDay( 1 );
Stream < LocalDate > stream = startOfYear.datesUntil( startOfYear.plusYears( 1 ) );
List < LocalDate > tuesdays = stream.filter( t -> t.getDayOfWeek().equals( DayOfWeek.TUESDAY ) ).collect( Collectors.toList() );
Joda-Time
Here is some example code in Joda-Time 2.4 for collecting all the Tuesdays in a year.
int year = 2014;
String input = year + "-01-01";
LocalDate localDateInput = LocalDate.parse( input );
LocalDate firstTuesday = localDateInput.withDayOfWeek ( DateTimeConstants.TUESDAY );
LocalDate tuesday = firstTuesday; // for incrementing by week.
List<LocalDate> list = new ArrayList<>();
while ( tuesday.getYear() == year ) {
list.add( tuesday );
tuesday.plusWeeks( 1 );
}
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.
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 adds 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 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.
I think your main problem lies in this condition
if (currentDayOfWeek >= dayOfWeek) {
since that will count any day that is "higher" than the day you want. If you pass 3, it will also count any day that is higher than 3, which isn't what you want.
the condition should be
if (currentDayOfWeek == dayOfWeek) {
I also recommend you use Calendar getTime method instead of parsing a String to get your Date.
I am somewhat struggling with this.
I want to setup my Calendar to let's say: Third Monday in February 2012.
And I didn't find any way of doing this using Java.
For example, if I wanted to set my calendar for Christmas 2011, I can do this easily, this way:
Calendar when = Calendar.getInstance();
when.set (Calendar.MONTH, Calendar.DECEMBER);
when.set (Calendar.DAY_OF_MONTH, 25)
when.set (Calendar.YEAR, 2011);
But I am lost as to how to set it up for let's say Memorial Day 2012, which is the last Monday of May. This is my code, but it's obviously wrong, because I simply can't assume that the last Monday of May will be in the 4th week of May that year:
Calendar when = Calendar.getInstance ();
when.set (Calendar.DAY_OF_WEEK,Calendar.MONDAY);
when.set (Calendar.MONTH, Calendar.MAY);
when.set (Calendar.WEEK_OF_MONTH, 4)
when.set (Calendar.YEAR, 2012);
Any suggestions as to how I can programatically find out, in which week of the month of May 2012 (in example above) is the last Monday? Assuming I can get that information, I should be able to get my code above to work.
I need something which would basically work for any other examples. Something which could give an exact day for the same scenarios. Examples:
Which date is:
3rd Thursday of May 2015
1st Monday of June 2050
4th Tuesday of December 2012
2nd Wednesday of July 2000
I really need this for my project and I am sure it's simple, but I am breaking my head on this without any real results to show for :) And also couldn't find anything on the net.
Added:
Ok, this is where I've got for the last Monday in a month:
when.set (GregorianCalendar.MONTH, GregorianCalendar.MAY);
when.set (GregorianCalendar.DAY_OF_WEEK, Calendar.MONDAY);
when.set (GregorianCalendar.DAY_OF_WEEK_IN_MONTH, -1);
when.set (Calendar.YEAR, 2012);
But I am not sure how would I go about doing for example seconds Monday in the same month, like this?
when.set (GregorianCalendar.DAY_OF_WEEK_IN_MONTH, 2);
Any suggestions?
To do date arithmetic in Java (and in general, to do anything with datetimes, except for the most trivial things) Joda-Time is the answer:
public static LocalDate getNDayOfMonth(int dayweek,int nthweek,int month,int year) {
LocalDate d = new LocalDate(year, month, 1).withDayOfWeek(dayweek);
if(d.getMonthOfYear() != month) d = d.plusWeeks(1);
return d.plusWeeks(nthweek-1);
}
public static LocalDate getLastWeekdayOfMonth(int dayweek,int month,int year) {
LocalDate d = new LocalDate(year, month, 1).plusMonths(1).withDayOfWeek(dayweek);
if(d.getMonthOfYear() != month) d = d.minusWeeks(1);
return d;
}
public static void main(String[] args) {
// second wednesday of oct-2011
LocalDate d = getNDayOfMonth( DateTimeConstants.WEDNESDAY, 2, 10, 2011);
System.out.println(d);
// last wednesday of oct-2011
LocalDate dlast = getLastWeekdayOfMonth( DateTimeConstants.WEDNESDAY, 10, 2011);
System.out.println(dlast);
}
Edit: Since Java 8 (2014) the new Date API (package java.time), which is inspired by/similar to Jodatime, should be preferred.
The following code was successfully tested for all holidays in 2013 and 2014. I realize that this doesn't really answer the original question, but I think it might be useful for people who come across this post in hopes of figuring out how to work with holidays using Calendar.
public static boolean isMajorHoliday(java.util.Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// check if New Year's Day
if (cal.get(Calendar.MONTH) == Calendar.JANUARY
&& cal.get(Calendar.DAY_OF_MONTH) == 1) {
return true;
}
// check if Christmas
if (cal.get(Calendar.MONTH) == Calendar.DECEMBER
&& cal.get(Calendar.DAY_OF_MONTH) == 25) {
return true;
}
// check if 4th of July
if (cal.get(Calendar.MONTH) == Calendar.JULY
&& cal.get(Calendar.DAY_OF_MONTH) == 4) {
return true;
}
// check Thanksgiving (4th Thursday of November)
if (cal.get(Calendar.MONTH) == Calendar.NOVEMBER
&& cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 4
&& cal.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) {
return true;
}
// check Memorial Day (last Monday of May)
if (cal.get(Calendar.MONTH) == Calendar.MAY
&& cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY
&& cal.get(Calendar.DAY_OF_MONTH) > (31 - 7) ) {
return true;
}
// check Labor Day (1st Monday of September)
if (cal.get(Calendar.MONTH) == Calendar.SEPTEMBER
&& cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 1
&& cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
return true;
}
// check President's Day (3rd Monday of February)
if (cal.get(Calendar.MONTH) == Calendar.FEBRUARY
&& cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 3
&& cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
return true;
}
// check Veterans Day (November 11)
if (cal.get(Calendar.MONTH) == Calendar.NOVEMBER
&& cal.get(Calendar.DAY_OF_MONTH) == 11) {
return true;
}
// check MLK Day (3rd Monday of January)
if (cal.get(Calendar.MONTH) == Calendar.JANUARY
&& cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 3
&& cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
return true;
}
return false;
}
I do not know the "easy" way but I can suggest you the following.
Set calendar to the first day of the month.
Retrieve its day of the week
Calculate the date of the first Monday of the month.
Add 14 days using calendar.add() method. You will get the third Monday.
tl;dr
LocalDate thirdMondayInFebruary2012 =
YearMonth.of( 2012 , Month.FEBRUARY )
.atDay( 1 )
.with( TemporalAdjusters.dayOfWeekInMonth( 3 , DayOfWeek.MONDAY ) );
…and…
LocalDate lastMondayInMay2012 =
YearMonth.of( 2012 , Month.MAY )
.atDay( 1 );
.with( TemporalAdjusters.lastInMonth( DayOfWeek.MONDAY ) );
java.time
Very easy to do using the java.time classes that now supplant both Joda-Time and the troublesome old date-time classes bundled with the earliest versions of Java.
First we need to specify the desired month. The YearMonth class can do that. From there we get a LocalDate, a date without a time-of-day and without a time zone.
YearMonth ym = YearMonth.of( 2012 , Month.FEBRUARY ); // Or pass '2' for 'February'.
LocalDate ld = ym.atDay( 1 );
The TemporalAdjuster interface provides for adjusting a date-time value into another date-time value. Implementations provided by the TemporalAdjusters class (notice the plural 's'). Specify a day of week using the handy DayOfWeek enum.
int ordinal = 3 ; // Use '3' for 'third occurrence in month' such as '3rd Monday'.
LocalDate thirdMondayInFebruary2012 = ld.with( TemporalAdjusters.dayOfWeekInMonth( ordinal , DayOfWeek.MONDAY ) );
Tip: Rather than pass mere integers for year and month across your code base, pass objects such as YearMonth, Year, Month, and DayOfWeek. Doing so eliminates ambiguity, makes your code more self-documenting, provides types-safety, and ensures valid values.
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.
All you need is a loop:
public class CalculateDate {
public static void main( String ... args ) {
Calendar c = Calendar.getInstance();
c.set( Calendar.YEAR, 2012 );
c.set( Calendar.MONTH , Calendar.MAY);
c.set( Calendar.DAY_OF_MONTH, 0 );
c.add( Calendar.DAY_OF_MONTH, -1 );
System.out.println( c.getTime() );
int mondaysCount = 0;
while ( mondaysCount != 4 ) {
c.add( Calendar.DAY_OF_MONTH, 1 );
if ( c.get( Calendar.DAY_OF_WEEK ) == Calendar.MONDAY ) {
mondaysCount++;
}
}
System.out.printf( "The fourth monday of may is %s", c.getTime() );
}
}
Any chances you are using Quartz scheduler?
public Date date(String cronExpression) {
return new org.quartz.CronExpression(cronExpression).
getNextValidTimeAfter(new Date(0));
}
System.out.println(date("0 0 0 ? May Thu#3 2015"));
System.out.println(date("0 0 0 ? Jun Mon#1 2050"));
System.out.println(date("0 0 0 ? Dec Tue#4 2012"));
System.out.println(date("0 0 0 ? Jul Wed#2 2000"));
This simple code prints correct (?) results:
Thu May 21 00:00:00 CEST 2015
Mon Jun 06 00:00:00 CEST 2050
Tue Dec 25 00:00:00 CET 2012
Wed Jul 12 00:00:00 CEST 2000
The required CronExpression doesn't have any dependencies on the rest of Quartz, so you might consider copying it to your project (watch out for license!)
Side note: the internal implementation of getNextValidTimeAfter() is 400 lines of code...
public String nDow(int year, int month, int nweek, int nday)
{
Calendar cdt = Calendar.getInstance();
cdt.set(year, month -1, 1);
return year + "-" + month + "-" + (getPosOfWeekday(cdt.get(Calendar.DAY_OF_WEEK), nday) + ((nweek - 1) *7));
}
private int getPosOfWeekday(int startday, int nday)
{
nday = weekDayValue(nday);
return constructCircularArray(startday).indexOf(nday) + 1;
}
private ArrayList<Integer> constructCircularArray(int weekday)
{
ArrayList<Integer> circularArray = new ArrayList<Integer>();
for(int i = 0; i < 7; i++)
{
circularArray.add(i, weekDayValue(weekday++));
}
return circularArray;
}
private int weekDayValue(int x)
{
return ((x-1) % 7) + 1;
}
Here is an alternative. What it does is: Get which week you want (n), and the other parameters, and return the date of the day in that week. Since Calendar gives the date of the previous month (for example 29th of February instead of 7th of March, since the 1st week of March collides with last week of Feb), the function computes the 2nd week if the date goes beyond 7 or multiples of it for each week thereof. Hope that helps.
public static int getNthWeekDay (int n, int day, int month, int year) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, day);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.WEEK_OF_MONTH,n);
calendar.set(Calendar.YEAR, year);
if (calendar.get(Calendar.DATE) > n * 7) {
calendar.set(Calendar.DAY_OF_WEEK,day);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.WEEK_OF_MONTH,day+1);
}
return calendar.get(Calendar.DATE);
}
I am new with using java.calendar.api.
I want to point to the previous working day for a given day using java.
BUT the conditions goes on increasing when i am using calendar.api to manipulate dates
since I had to consider the usual weekends and the pointing to the previous month and also i had to consider the regional holidays in my region......
for ex:say i had to consider the U.S holidays and point to the day before that.
Is there any way i can define my own calendar and use it so that date manipulation senses all those usual changes?
While you should consider using the Joda Time library, here's a start with the Java Calendar API:
public Date getPreviousWorkingDay(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int dayOfWeek;
do {
cal.add(Calendar.DAY_OF_MONTH, -1);
dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
} while (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY);
return cal.getTime();
}
This only considers weekends. You'll have to add additional checks to handle days you consider holidays. For instance you could add || isHoliday(cal) to the while condition. Then implement that method, something like:
public boolean isHoliday(Calendar cal) {
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;
int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
if (month == 12 && dayOfMonth == 25) {
return true;
}
// more checks
return false;
}
tl;dr
LocalDate.now ( ZoneId.of ( "America/Montreal" ) )
.with ( org.threeten.extra.Temporals.previousWorkingDay () )
java.time
Java 8 and later has the java.time framework built-in. Inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project.
These new classes replace the notoriously troublesome old date-time classes bundled with the earliest versions of Java, java.util.Date/.Calendar. Avoid the old classes where possible. When you must interface look for newly added conversion methods to switch into java.time for most of your work. Also, the makers of Joda-Time have told us to move to java.time as soon as is convenient.
Basics of java.time… An Instant is a moment on the timeline in UTC. Apply a time zone (ZoneId) to get a ZonedDateTime. For a date-only value without a time-of-day nor a time zone, use LocalDate.
First we get "today" as an example date value. Note how a time zone is required in order to determine the current date even though a LocalDate does not contain a time zone. The date is not simultaneously the same around the globe, as a new day dawns earlier in the east.
LocalDate today = LocalDate.now ( ZoneId.of ( "America/Los_Angeles" ) );
Adjustors
The ThreeTen-Extra project extends java.time with additional or experimental features. These features may or may not eventually be folded into java.time proper. This project provides a Temporals class which provides implementations of adjustors including a couple for nextWorkingDay and previousWorkingDay. Easy to use as seen here.
// The 'Temporals' class is from the ThreeTen-Extra library, not built into Java.
LocalDate previousWorkingDay = today.with ( Temporals.previousWorkingDay () );
LocalDate nextWorkingDay = today.with ( Temporals.nextWorkingDay () );
When Run
Dump to console. Notice how today is a Friday, so the previous working day is -1 (yesterday, Thursday) and the next working day is +3 (Monday).
System.out.println ( "today: " + today + " | previousWorkingDay: " + previousWorkingDay + " | nextWorkingDay: " + nextWorkingDay );
today: 2016-01-22 | previousWorkingDay: 2016-01-21 | nextWorkingDay: 2016-01-25
Saturday & Sunday
This pair of adjustors simply skips over every Saturday and Sunday. It knows nothing of holidays. Nor does it know about other definitions of the working week and weekend. The class documentation suggests writing your own java.time.temporal.TemporalAdjuster is easy if you want to handle other definitions.
Consider using Joda Time combined with a list of regional holidays in your region.
You may define a class as below:
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
*
* #author j.james
*/
public class MyCalendar {
private static Map<String, String> holidays = null;
private static MyCalendar myCalendar = null;
private static final int WEEKEND_1 = Calendar.SATURDAY;
private static final int WEEKEND_2 = Calendar.SUNDAY;
private MyCalendar() {
holidays = new HashMap<String, String>();
holidays.put("7,4", "Independence Day");
holidays.put("12,25", "Christmas");
//holidays.putAll(DBUtils.readAnyDynamicHolidaysFromDB());
}
public static Date getPreviousWorkingDay(Date date) {
Date previousWorkingDate = null;
try {
if (myCalendar == null) {
myCalendar = new MyCalendar();
}
if(date != null) {
Calendar calInstance = Calendar.getInstance();
calInstance.setTime(date);
int weekDay = 0;
do {
calInstance.add(Calendar.DATE, -1);
weekDay = calInstance.get(Calendar.DAY_OF_WEEK);
} while(weekDay == WEEKEND_1 || weekDay == WEEKEND_2 ||
holidays.get((calInstance.get(Calendar.MONTH) + 1)
+ "," + calInstance.get(Calendar.DATE)) != null);
previousWorkingDate = calInstance.getTime();
}
} catch (Exception e) {
e.printStackTrace();
}
return previousWorkingDate;
}
}
You can make a call as
public static void main(String[] args) {
System.out.println(MyCalendar.getPreviousWorkingDay(new Date(2011-1900,6,5))); //July 5, 2011 which returns July 1 as the working day because July 4th 2011 is Monday
}
I have start date and end date.
I need the number of months between this two dates in Java.
For example
From date: 2009-01-29
To date: 2009-02-02
It has one jan date and one Feb date.
It should return 2.
As the rest say, if there's a library that will give you time differences in months, and you can use it, then you might as well.
Otherwise, if y1 and m1 are the year and month of the first date, and y2 and m2 are the year and month of the second, then the value you want is:
(y2 - y1) * 12 + (m2 - m1) + 1;
Note that the middle term, (m2 - m1), might be negative even though the second date is after the first one, but that's fine.
It doesn't matter whether months are taken with January=0 or January=1, and it doesn't matter whether years are AD, years since 1900, or whatever, as long as both dates are using the same basis. So for example don't mix AD and BC dates, since there wasn't a year 0 and hence BC is offset by 1 from AD.
You'd get y1 etc. either from the dates directly if they're supplied to you in a suitable form, or using a Calendar.
Apart from using Joda time which seems to be the the favorite suggestion I'd offer the following snippet:
public static final int getMonthsDifference(Date date1, Date date2) {
int m1 = date1.getYear() * 12 + date1.getMonth();
int m2 = date2.getYear() * 12 + date2.getMonth();
return m2 - m1 + 1;
}
EDIT: Since Java 8, there is a more standard way of calculating same difference. See my alternative answer using JSR-310 api instead.
I would strongly recommend Joda-Time (and as of Java 8, the Java Time apis) for this.
It makes this sort of work very easy (check out Periods)
It doesn't suffer from the threading issues plaguing the current date/time objects (I'm thinking of formatters, particularly)
It's the basis of the new Java date/time APIs to come with Java 7 (so you're learning something that will become standard)
Note also Nick Holt's comments below re. daylight savings changes.
Now that JSR-310 has been included in the SDK of Java 8 and above, here's a more standard way of getting months difference of two date values:
public static final long getMonthsDifference(Date date1, Date date2) {
YearMonth m1 = YearMonth.from(date1.toInstant().atZone(ZoneOffset.UTC));
YearMonth m2 = YearMonth.from(date2.toInstant().atZone(ZoneOffset.UTC));
return m1.until(m2, ChronoUnit.MONTHS) + 1;
}
This has a benefit of clearly spelling out the precision of the calculation and it is very easy to understand what is the intent of the calculation.
Java 8 solution:
#Test
public void monthBetween() {
LocalDate d1 = LocalDate.of(2013, Month.APRIL, 1);
LocalDate d2 = LocalDate.of(2014, Month.APRIL, 1);
long monthBetween = ChronoUnit.MONTHS.between(d1, d2);
assertEquals(12, monthBetween);
}
Based on the above suggested answers I rolled my own which I added to my existing DateUtils class:
public static Integer differenceInMonths(Date beginningDate, Date endingDate) {
if (beginningDate == null || endingDate == null) {
return 0;
}
Calendar cal1 = new GregorianCalendar();
cal1.setTime(beginningDate);
Calendar cal2 = new GregorianCalendar();
cal2.setTime(endingDate);
return differenceInMonths(cal1, cal2);
}
private static Integer differenceInMonths(Calendar beginningDate, Calendar endingDate) {
if (beginningDate == null || endingDate == null) {
return 0;
}
int m1 = beginningDate.get(Calendar.YEAR) * 12 + beginningDate.get(Calendar.MONTH);
int m2 = endingDate.get(Calendar.YEAR) * 12 + endingDate.get(Calendar.MONTH);
return m2 - m1;
}
And the associatiated unit tests:
public void testDifferenceInMonths() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
assertEquals(12, DateUtils.differenceInMonths(sdf.parse("2014/03/22"), sdf.parse("2015/03/22")).intValue());
assertEquals(11, DateUtils.differenceInMonths(sdf.parse("2014/01/01"), sdf.parse("2014/12/25")).intValue());
assertEquals(88, DateUtils.differenceInMonths(sdf.parse("2014/03/22"), sdf.parse("2021/07/05")).intValue());
assertEquals(6, DateUtils.differenceInMonths(sdf.parse("2014/01/22"), sdf.parse("2014/07/22")).intValue());
}
using joda time would be like this (i compared how many months between today and 20/dec/2012)
import org.joda.time.DateTime ;
import org.joda.time.Months;
DateTime x = new DateTime().withDate(2009,12,20); // doomsday lol
Months d = Months.monthsBetween( new DateTime(), x);
int monthsDiff = d.getMonths();
Result: 41 months (from july 6th 2009)
should be easy ? :)
ps: you can also convert your date using SimpleDateFormat
like:
Date x = new SimpleDateFormat("dd/mm/yyyy").parse("20/12/2009");
DateTime z = new DateTime(x);
If you don't want to use Joda (for whatever reason), you can convert your date to TimeStamp and then do the differences of milli seconds between both date and then calculate back to months. But I still prefer to use Joda time for the simplicity :)
tl;dr
ChronoUnit.MONTHS.between(
YearMonth.from( LocalDate.of( 2009 , 1 , 29 ) ) ,
YearMonth.from( LocalDate.of( 2009 , 2 , 2 ) )
)
Time Zone
The Answer by Roland Tepp is close but ignores the crucial issue of time zone. Determining a month and date requires a time zone, as for any given moment the date varies around the globe by zone.
ZonedDateTime
So his example of converting java.util.Date objects to java.time.Instant objects implicitly uses UTC. Values in either of those classes is always in UTC by definition. So you need to adjust those objects into the desired/intended time zone to be able to extract a meaningful date.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtStart = myJavaUtilDate1.toInstant().atZone( z );
ZonedDateTime zdtStop = myJavaUtilDate2.toInstant().atZone( z );
YearMonth
Since you want to know how many calendar months were touched by your date range rather than the number of 30-day chunks elapsed, convert to YearMonth objects.
YearMonth start = YearMonth.from( zdtStart );
YearMonth stop = YearMonth.from( zdtStop );
ChronoUnit
Calculate months between by calling on ChronoUnit enum.
long monthsBetween = ChronoUnit.MONTHS.between( start , stop );
1
Half-Open
You desired a result of 2 but we get 1 here. The reason is that in date-time work the best practice is to define spans of time by the Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive. I suggest you stick to this definition throughout your date-time work as doing so ultimately makes sense, eliminates confusing ambiguities, and makes your work easier to parse mentally and less error-prone. But if you insist on your definition, simply add 1 to the result assuming you have positive numbered results (meaning your spans of time go forward in time rather than backward).
LocalDate
The original Question is not clear but may require date-only values rather than date-time values. If so, use the LocalDate class. The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate start = LocalDate.of( 2009 , 1 , 29 ) ;
LocalDate stop = LocalDate.of( 2009 , 2 , 2 ) ;
long monthsBetween = ChronoUnit.MONTHS.between( start , stop );
1
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.
Joda Time is a pretty cool library for Java Date and Time and can help you achieve what you want using Periods.
You can use a Calendar or Joda time library for this.
In Joda time you can use the Days.daysBetween() method. You can then calculate the months difference. You can also use DateTime.getMonthOfYear() and do a subtraction (for dates in the same year).
It depends on your definition of a month, but this is what we use:
int iMonths = 0;
Calendar cal1 = GregorianCalendar.getInstance();
cal1.setTime(date1);
Calendar cal2 = GregorianCalendar.getInstance();
cal2.setTime(date2);
while (cal1.after(cal2)){
cal2.add(Calendar.MONTH, 1);
iMonths++;
}
if (cal2.get(Calendar.DAY_OF_MONTH) > cal1.get(Calendar.DAY_OF_MONTH)){
iMonths--;
}
return iMonths;
I had to write this implementation, becoz I had custom defined periods, which i had to look for within two dates.
Here you can define you custom period and put the logic, for calculation.
Here TimePeriod is a POJO which has start, end, period start, period End
public class Monthly extends Period {
public int getPeriodCount(String startDate, String endDate, int scalar) {
int cnt = getPeriods(startDate, endDate, scalar).size();
return cnt;
}
public List getPeriods(String startDate, String endDate, int scalar) {
ArrayList list = new ArrayList();
Calendar startCal = CalendarUtil.getCalendar(startDate);
Calendar endCal = CalendarUtil.getCalendar(endDate);
while (startCal.compareTo(endCal) <= 0) {
TimePeriod period = new TimePeriod();
period.setStartDate(startCal.getTime());
period.setPeriodStartDate(getPeriodStartDate((Calendar) startCal.clone()).getTime());
Calendar periodEndCal = getPeriodEndDate((Calendar) startCal.clone(), scalar);
period.setEndDate(endCal.before(periodEndCal) ? endCal.getTime() : periodEndCal.getTime());
period.setPeriodEndDate(periodEndCal.getTime());
periodEndCal.add(Calendar.DATE, 1);
startCal = periodEndCal;
list.add(period);
}
return list;
}
private Calendar getPeriodStartDate(Calendar cal) {
cal.set(Calendar.DATE, cal.getActualMinimum(Calendar.DATE));
return cal;
}
private Calendar getPeriodEndDate(Calendar cal, int scalar) {
while (scalar-- > 0) {
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
if (scalar > 0)
cal.add(Calendar.DATE, 1);
}
return cal;
}
}
it is not the best anwer but you can use unixtimestamp
First you find the unixtime's of the dates
then eject each other
Finally you should convert the unixtime(sum) to String
That's because the classes Java Date and Calendar use the Month indices from 0-11
January = 0
December = 1
Is recommended to use Joda Time!
Here's a solution using java.util.Calendar object:
private static Integer getMonthsBetweenDates(Date d1, Date d2) {
Calendar todayDate = getCalendar(d1);
Calendar pastDate = getCalendar(d2);
int yearDiff = todayDate.get(Calendar.YEAR) - pastDate.get(Calendar.YEAR);
if (pastDate.get(Calendar.MONTH) < 11 && pastDate.get(Calendar.DAY_OF_MONTH) < 31){ //if pastDate is smaller than 31/12
yearDiff++;
}
int monthCount = 0;
for (int year = 0 ; year < yearDiff ; year++){
if (year == 0) {
monthCount += 12 - pastDate.get(Calendar.MONTH);
} else if (year == yearDiff - 1){ //last year
if (todayDate.get(Calendar.MONTH) < pastDate.get(Calendar.MONTH)){
monthCount += todayDate.get(Calendar.MONTH) + 1;
} else if (todayDate.get(Calendar.MONTH) >= pastDate.get(Calendar.MONTH) && todayDate.get(Calendar.DAY_OF_MONTH) < pastDate.get(Calendar.DAY_OF_MONTH)){
monthCount += todayDate.get(Calendar.MONTH);
} else if (todayDate.get(Calendar.MONTH) >= pastDate.get(Calendar.MONTH) && todayDate.get(Calendar.DAY_OF_MONTH) >= pastDate.get(Calendar.DAY_OF_MONTH)){
monthCount += todayDate.get(Calendar.MONTH) + 1;
}
}
for (int months = 0 ; months < 12 ; months++){
if (year > 0 && year < yearDiff -1){
monthCount++;
}
}
}
return monthCount;
}
Why not calculate with full timedate
public static Integer calculateMonthDiff(Date begining, Date end) throws Exception {
if (begining.compareTo(end) > 0) {
throw new Exception("Beginning date is greater than the ending date");
}
if (begining.compareTo(end) == 0) {
return 0;
}
Calendar cEndCheckDate = Calendar.getInstance();
cEndCheckDate.setTime(begining);
int add = 0;
while (true) {
cEndCheckDate.add(Calendar.MONTH, 1);
add++;
if (cEndCheckDate.getTime().compareTo(end) > 0) {
return add - 1;
}
}
}
A full code snippet for finding the difference of months between two date is as follows:
public String getContractMonth(String contractStart, String contractEnd) {
SimpleDateFormat dfDate = new SimpleDateFormat("yyyy-MM-dd");
String months = "0";
try {
Date startDate = dfDate.parse(contractStart);
Date endDate = dfDate.parse(contractEnd);
Calendar startCalendar = Calendar.getInstance();
startCalendar.setTime(startDate);
Calendar endCalendar = Calendar.getInstance();
endCalendar.setTime(endDate);
int diffYear = endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR);
int diffMonth = diffYear * 12 + endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);
months = diffMonth + "";
} catch (ParseException e) {
e.printStackTrace();
} catch (java.text.ParseException e) {
e.printStackTrace();
}
return months;
}
below logic will fetch you difference in months
(endCal.get(Calendar.YEAR)*12+endCal.get(Calendar.MONTH))-(startCal.get(Calendar.YEAR)*12+startCal.get(Calendar.MONTH))
you can by 30 days or by months :
public static void main(String[] args) throws IOException {
int n = getNumbertOfMonth(LocalDate.parse("2016-08-31"),LocalDate.parse("2016-11-30"));
System.out.println("number of month = "+n);
n = getNumbertOfDays(LocalDate.parse("2016-08-31"),LocalDate.parse("2016-11-30"));
System.out.println("number of days = "+n);
System.out.println("number of 30 days = "+n/30);
}
static int getNumbertOfMonth(LocalDate dateDebut, LocalDate dateFin) {
LocalDate start = dateDebut;
LocalDate end = dateFin;
int count = 0 ;
List<String> lTotalDates = new ArrayList<>();
while (!start.isAfter(end)) {
count++;
start = start.plusMonths(1);
}
return count;
}
static int getNumbertOfDays(LocalDate dateDebut, LocalDate dateFin) {
LocalDate start = dateDebut;
LocalDate end = dateFin;
int count = 0 ;
List<String> lTotalDates = new ArrayList<>();
while (!start.isAfter(end)) {
count++;
start = start.plusDays(1);
}
return count;
}
long monthsBetween = ChronoUnit.MONTHS.between(LocalDate.parse("2016-01-29").minusMonths(1),
LocalDate.parse("2016-02-02").plusMonths(1));
2016-01-29 to 2016-01-02 = months 1
2016-02-29 to 2016-02-02 = months 1
2016-03-29 to 2016-05-02 = months 5
Here a complete implementation for monthDiff in java without iterations. It returns the number of full month between two dates. If you want to include the number of incomplete month in the result (as in the initial question), you have to zero out the day, hours, minutes, seconds and millisecondes of the two dates before calling the method, or you could change the method to not compare days, hours, minutes etc.
import java.util.Date;
import java.util.Calendar;
...
public static int monthDiff(Date d1, Date d2) {
int monthDiff;
Calendar c1, c2;
int M1, M2, y1, y2, t1, t2, h1, h2, m1, m2, s1, s2, ms1, ms2;
c1 = Calendar.getInstance();
c1.setTime(d1);
c2 = Calendar.getInstance();
c2.setTime(d2);
M1 = c1.get(Calendar.MONTH);
M2 = c2.get(Calendar.MONTH);
y1 = c1.get(Calendar.YEAR);
y2 = c2.get(Calendar.YEAR);
t1 = c1.get(Calendar.DAY_OF_MONTH);
t2 = c2.get(Calendar.DAY_OF_MONTH);
if(M2 < M1) {
M2 += 12;
y2--;
}
monthDiff = 12*(y2 - y1) + M2 - M1;
if(t2 < t1)
monthDiff --; // not a full month
else if(t2 == t1) { // perhaps a full month, we have to look into the details
h1 = c1.get(Calendar.HOUR_OF_DAY);
h2 = c2.get(Calendar.HOUR_OF_DAY);
if(h2 < h1)
monthDiff--; // not a full month
else if(h2 == h1) { // go deeper
m1 = c1.get(Calendar.MINUTE);
m2 = c2.get(Calendar.MINUTE);
if(m2 < m1) // not a full month
monthDiff--;
else if(m2 == m1) { // look deeper
s1 = c1.get(Calendar.SECOND);
s2 = c2.get(Calendar.SECOND);
if(s2 < s1)
monthDiff--; // on enleve l'age de mon hamster
else if(s2 == s1) {
ms1 = c1.get(Calendar.MILLISECOND);
ms2 = c2.get(Calendar.MILLISECOND);
if(ms2 < ms1)
monthDiff--;
// else // it's a full month yeah
}
}
}
}
return monthDiff;
}
So many answers with long code when you can just do it with 1 line and some math:
LocalDate from = yourdate;
LocalDate to = yourotherdate;
int difference = to.getMonthValue() - from.getMonthValue()) + ((to.getYear() - from.getYear()) * 12) + 1;