How to skip weekends while adding days to LocalDate in Java 8? - java

Other answers here refer to Joda API.
I want to do it using java.time.
Suppose today's date is 26th Nov 2015-Thursday, when I add 2 business days to it,
I want the result as Monday 30th Nov 2015.
I am working on my own implementation but it would be great if something already exists!
EDIT:
Is there a way to do it apart from looping over?
I was trying to derive a function like:
Y = f(X1,X2) where
Y is actual number of days to add,
X1 is number of business days to add,
X2 is day of the week (1-Monday to 7-Sunday)
Then given X1 and X2 (derived from day of week of the date), we can find Y and then use plusDays() method of LocalDate.
I have not been able to derive it so far, its not consistent. Can anyone confirm that looping over until desired number of workdays are added is the only way?

The following method adds days one by one, skipping weekends, for positive values of workdays:
public LocalDate add(LocalDate date, int workdays) {
if (workdays < 1) {
return date;
}
LocalDate result = date;
int addedDays = 0;
while (addedDays < workdays) {
result = result.plusDays(1);
if (!(result.getDayOfWeek() == DayOfWeek.SATURDAY ||
result.getDayOfWeek() == DayOfWeek.SUNDAY)) {
++addedDays;
}
}
return result;
}
After some fiddling around, I came up with an algorithm to calculate the number of workdays to add or subtract.
/**
* #param dayOfWeek
* The day of week of the start day. The values are numbered
* following the ISO-8601 standard, from 1 (Monday) to 7
* (Sunday).
* #param businessDays
* The number of business days to count from the day of week. A
* negative number will count days in the past.
*
* #return The absolute (positive) number of days including weekends.
*/
public long getAllDays(int dayOfWeek, long businessDays) {
long result = 0;
if (businessDays != 0) {
boolean isStartOnWorkday = dayOfWeek < 6;
long absBusinessDays = Math.abs(businessDays);
if (isStartOnWorkday) {
// if negative businessDays: count backwards by shifting weekday
int shiftedWorkday = businessDays > 0 ? dayOfWeek : 6 - dayOfWeek;
result = absBusinessDays + (absBusinessDays + shiftedWorkday - 1) / 5 * 2;
} else { // start on weekend
// if negative businessDays: count backwards by shifting weekday
int shiftedWeekend = businessDays > 0 ? dayOfWeek : 13 - dayOfWeek;
result = absBusinessDays + (absBusinessDays - 1) / 5 * 2 + (7 - shiftedWeekend);
}
}
return result;
}
Usage Example:
LocalDate startDate = LocalDate.of(2015, 11, 26);
int businessDays = 2;
LocalDate endDate = startDate.plusDays(getAllDays(startDate.getDayOfWeek().getValue(), businessDays));
System.out.println(startDate + (businessDays > 0 ? " plus " : " minus ") + Math.abs(businessDays)
+ " business days: " + endDate);
businessDays = -6;
endDate = startDate.minusDays(getAllDays(startDate.getDayOfWeek().getValue(), businessDays));
System.out.println(startDate + (businessDays > 0 ? " plus " : " minus ") + Math.abs(businessDays)
+ " business days: " + endDate);
Example Output:
2015-11-26 plus 2 business days: 2015-11-30
2015-11-26 minus 6 business days: 2015-11-18

Here is a version which supports both positive and negative number of days and exposes the operation as a TemporalAdjuster. That allows you to write:
LocalDate datePlus2WorkingDays = date.with(addWorkingDays(2));
Code:
/**
* Returns the working day adjuster, which adjusts the date to the n-th following
* working day (i.e. excluding Saturdays and Sundays).
* <p>
* If the argument is 0, the same date is returned if it is a working day otherwise the
* next working day is returned.
*
* #param workingDays the number of working days to add to the date, may be negative
*
* #return the working day adjuster, not null
*/
public static TemporalAdjuster addWorkingDays(long workingDays) {
return TemporalAdjusters.ofDateAdjuster(d -> addWorkingDays(d, workingDays));
}
private static LocalDate addWorkingDays(LocalDate startingDate, long workingDays) {
if (workingDays == 0) return nextOrSameWorkingDay(startingDate);
LocalDate result = startingDate;
int step = Long.signum(workingDays); //are we going forward or backward?
for (long i = 0; i < Math.abs(workingDays); i++) {
result = nextWorkingDay(result, step);
}
return result;
}
private static LocalDate nextOrSameWorkingDay(LocalDate date) {
return isWeekEnd(date) ? nextWorkingDay(date, 1) : date;
}
private static LocalDate nextWorkingDay(LocalDate date, int step) {
do {
date = date.plusDays(step);
} while (isWeekEnd(date));
return date;
}
private static boolean isWeekEnd(LocalDate date) {
DayOfWeek dow = date.getDayOfWeek();
return dow == SATURDAY || dow == SUNDAY;
}

Determining business days is fundamentally a question of looping over dates, checking if each is a weekend or holiday.
The Strata project from OpenGamma (I am a committer) has an implementation of a holiday calendar. The API covers the case of finding the date 2 business days later. The implementation has an optimized bitmap design that performs better than day by day looping. It may be of interest here.

This is a way to add business days using java.time Classes, some functional interfaces & lambda...
IntFunction<TemporalAdjuster> addBusinessDays = days -> TemporalAdjusters.ofDateAdjuster(
date -> {
LocalDate baseDate =
days > 0 ? date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
: days < 0 ? date.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY)) : date;
int businessDays = days + Math.min(Math.max(baseDate.until(date).getDays(), -4), 4);
return baseDate.plusWeeks(businessDays / 5).plusDays(businessDays % 5);
});
LocalDate.of(2018, 1, 5).with(addBusinessDays.apply(2));
//Friday Jan 5, 2018 -> Tuesday Jan 9, 2018
LocalDate.of(2018, 1, 6).with(addBusinessDays.apply(15));
//Saturday Jan 6, 2018 -> Friday Jan 26, 2018
LocalDate.of(2018, 1, 7).with(addBusinessDays.apply(-10));
//Sunday Jan 7, 2018 -> Monday Dec 25, 2017
Supports negative values and from any week day!

This is a method which is adding or subtracting workdays to a given calendar object:
/**
* This method adds workdays (MONDAY - FRIDAY) to a given calendar object.
* If the number of days is negative than this method subtracts the working
* days from the calendar object.
*
*
* #param cal
* #param days
* #return new calendar instance
*/
public static Calendar addWorkDays(final Calendar baseDate, final int days) {
Calendar resultDate = null;
Calendar workCal = Calendar.getInstance();
workCal.setTime(baseDate.getTime());
int currentWorkDay = workCal.get(Calendar.DAY_OF_WEEK);
// test if SATURDAY ?
if (currentWorkDay == Calendar.SATURDAY) {
// move to next FRIDAY
workCal.add(Calendar.DAY_OF_MONTH, (days < 0 ? -1 : +2));
currentWorkDay = workCal.get(Calendar.DAY_OF_WEEK);
}
// test if SUNDAY ?
if (currentWorkDay == Calendar.SUNDAY) {
// move to next FRIDAY
workCal.add(Calendar.DAY_OF_MONTH, (days < 0 ? -2 : +1));
currentWorkDay = workCal.get(Calendar.DAY_OF_WEEK);
}
// test if we are in a working week (should be so!)
if (currentWorkDay >= Calendar.MONDAY && currentWorkDay <= Calendar.FRIDAY) {
boolean inCurrentWeek = false;
if (days > 0)
inCurrentWeek = (currentWorkDay + days < 7);
else
inCurrentWeek = (currentWorkDay + days > 1);
if (inCurrentWeek) {
workCal.add(Calendar.DAY_OF_MONTH, days);
resultDate = workCal;
} else {
int totalDays = 0;
int daysInCurrentWeek = 0;
// fill up current week.
if (days > 0) {
daysInCurrentWeek = Calendar.SATURDAY - currentWorkDay;
totalDays = daysInCurrentWeek + 2;
} else {
daysInCurrentWeek = -(currentWorkDay - Calendar.SUNDAY);
totalDays = daysInCurrentWeek - 2;
}
int restTotalDays = days - daysInCurrentWeek;
// next working week... add 2 days for each week.
int x = restTotalDays / 5;
totalDays += restTotalDays + (x * 2);
workCal.add(Calendar.DAY_OF_MONTH, totalDays);
resultDate = workCal;
}
}
return resultDate;
}

Example:
Calculate the total number of days from the date I started working except Saturday and Sunday.
public class App {
public static void main(String[] args) throws Exception {
/** I write the code when 2019-8-15 */
LocalDate now = LocalDate.now();
LocalDate startWork = LocalDate.parse("2019-06-17");
/** get all days */
long allDays = Duration.between(startWork.atStartOfDay(), now.atStartOfDay()).toDays() + 1;
System.out.println("This is the " + allDays + "th day you enter the company.");
/** variable to store day except sunday and saturday */
long workDays = allDays;
for (int i = 0; i < allDays; i++) {
if (startWork.getDayOfWeek() == DayOfWeek.SATURDAY || startWork.getDayOfWeek() == DayOfWeek.SUNDAY) {
workDays--;
}
startWork = startWork.plusDays(1);
}
System.out.println("You actually work for a total of " + workDays + " days.");
}
}
/**
This is the 60th day you enter the company.
You actually work for a total of 44 days.
*/
Hope that can help you.

Related

Calculate different between two dates result I need months and days only (without Year)

I got this class in java to calculate efferent between two dates but
the result coming with year I need this only month and days. Example 1
year 2 months 5 days is result. I need Result 14 month 5 days
Java code for date different calculation
public String getPeriod(Date a, Date b) {
Calendar startDay = Calendar.getInstance();
startDay.setTimeInMillis(a.getTime());
//create calendar object for current day
Calendar endDay = Calendar.getInstance();
endDay.setTimeInMillis(b.getTime());
//Get difference between years
years = endDay.get(Calendar.YEAR) - startDay.get(Calendar.YEAR);
int deathMonth = endDay.get(Calendar.MONTH) + 1;
int openMonth = startDay.get(Calendar.MONTH) + 1;
months = deathMonth - openMonth;
//if month difference is in negative then reduce years by one
//and calculate the number of months.
if (months < 0)
{
years--;
months = 12 - openMonth + deathMonth;
if (endDay.get(Calendar.DATE) < startDay.get(Calendar.DATE))
months--;
}
else if (months == 0 && endDay.get(Calendar.DATE) < startDay.get(Calendar.DATE))
{
years--;
months = 11;
}
//Calculate the days
if (endDay.get(Calendar.DATE) > startDay.get(Calendar.DATE))
days = endDay.get(Calendar.DATE) - startDay.get(Calendar.DATE);
else if (endDay.get(Calendar.DATE) < startDay.get(Calendar.DATE))
{
int today = endDay.get(Calendar.DAY_OF_MONTH);
endDay.add(Calendar.MONTH, -1);
days = endDay.getActualMaximum(Calendar.DAY_OF_MONTH) - startDay.get(Calendar.DAY_OF_MONTH) + today;
}
else
{
days = 0;
if (months == 12)
{
years++;
months = 0;
}
}
return (months+","+days+","+years);
}
Consider implementing your getPeriod() method using java's date-time API that was introduced in Java 8. Below is such an implementation:
/* Required imports.
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.ChronoUnit;
*/
private static String getPeriod(LocalDate start, LocalDate end) {
long months = ChronoUnit.MONTHS.between(start, end);
long days = ChronoUnit.DAYS.between(start.plusMonths(months), end);
return String.format("%d months %d days", months, days);
}
If you call the method like so:
LocalDate start = LocalDate.of(2020, Month.JANUARY, 1);
LocalDate end = LocalDate.of(2020, Month.APRIL, 29);
getPeriod(start, end);
The method will return the following string:
3 months 28 days
Refer to the Date Time trail in Oracle's java tutorials.

Printing only business working days

I've been stuck on this issue for the past 4 hours trying different strategies which haven't prevailed much at all having checked countless posts on here and Google. Basically what I am trying to do is print out only the business working days within a week mon-fri. I have tried incrementing the day of the year each time the weekend days come up but of course this messes up the order of the days after. For example instead of having:
Iteration: 0, 1, 2, 3, 4, 5, 6, 7, 8....
Day: (0)Friday, (1)Saturday, (2)Sunday, (3)Monday, (4)Tuesday, (5)Wednesday, (6)Thursday, (7)Friday, (8)Saturday....etc
I require:
Day: (0)Friday, (1)Monday, (2)Tuesday (3)Wednesday, (4)Thursday, (5)Friday, (6)Monday, (7)Tuesday, (8)Wednesday....etc
Here's the code:
public static void date(int day) {
now = Calendar.getInstance();
//SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");//version 1
SimpleDateFormat format = new SimpleDateFormat("EEEE d MMMM yyyy"); //version 2
String[] days = new String[maxDayCount]; //limits the number of days to print out(ordinarily h)
now.add(Calendar.DAY_OF_YEAR, day + 1); //Increments from test count + 1 due to count starting at 0 (would be today). Increments the date to get from today.
int DayOfWeek = now.get(Calendar.DAY_OF_WEEK);
boolean WorkingDayCheck = ((DayOfWeek >= Calendar.MONDAY) && (DayOfWeek <= Calendar.FRIDAY));
if(WorkingDayCheck) {
days[day] = format.format(now.getTime());
} else {
//
}
now.add(Calendar.DAY_OF_MONTH, 1);
System.out.println("-----------Day " + day + ": " + String.valueOf(days[day])); //v2: print out each line
}//END OF METHOD: date
The idea is that I have an iteration elsewhere which passes the day number to this method in order for this to use that number to then print out the date. I am now back to what I was with originally before trying a load of things which at the moment with the check I am doing with the WorkingDayCheck boolean the print out is of course returning null when the weekend days come about.
Any ideas chaps?
Thanks for your time.
I think this will solve your problem.
First, why do you define the array days each time you enter the method then you populate only one value in it?
Your String[] days = new String[maxDayCount]; should be a member variable not a local variable. So initialize this array outside this method.
Also initialize another int that represent the last empty location in your array. (defaults to 0)
public class Foo {
int maxDayCount = 365;
String[] days = new String[maxDayCount];
int finalIndex = 0;
public static void date(int day) {
now = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("EEEE d MMMM yyyy");
String[] days = new String[maxDayCount]; //limits the number of days to print out(ordinarily h)
now.add(Calendar.DAY_OF_YEAR, day + 1); //Increments from test count + 1 due to count starting at 0 (would be today). Increments the date to get from today.
int DayOfWeek = now.get(Calendar.DAY_OF_WEEK);
boolean WorkingDayCheck = ((DayOfWeek >= Calendar.MONDAY) && (DayOfWeek <= Calendar.FRIDAY));
if(WorkingDayCheck) {
days[finalIndex++] = format.format(now.getTime());
System.out.print("(" + (finalIndex - 1) + ")" + String.valueOf(days[finalIndex - 1]))
} else {
//
}
}
public static void main(String[]args) {
int day = 0;
while(finalIndex != maxDaysCount) {
date(day++);
}
}
}
Now your days array will be populated with working days only in their respective indices. For example in days[0] will be Friday then days[1] will be Saturday and so on since you have a pointer finalIndex that is independent of the value of day that is input to your method from the iteration.
If I get your problem correctly you want to do somewhat like following,
Working Day #1 = 0 Week + 1 Day = 1st Day
..
Working Day #5 = 0 Week + 5 Days = 5th Day
Working Day #6 = 1 Week + 1 Day = 8th Day
..
Working Day #10 = 1 Week + 5 Days = 12th Day
And then print the 1st,2nd,3rd calendar day of the year.
If that is the case you can try finding the calendar day from working day like something,
int div = day/5;
int rem = day%5;
int calendarDay = 0;
if(day>5){
if(rem == 0)
calendarDay = (div-1)*7 + 5;
else
calendarDay = div*7 + rem;
}else
calendarDay = day;
And then find the Calendar day for that date like
Calendar calendar = new GregorianCalendar();
calendar.set(Calendar.DAY_OF_YEAR, day);
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb, Locale.ENGLISH);
formatter.format("%tD", calendar);
System.out.println(sb);
The code is not a solution, but I guess it points to where you want to go.
Having played around with the code I have achieved what I was after now with:
public static String getDate4(int day) {
now = Calendar.getInstance();
//SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");//version 1
SimpleDateFormat format = new SimpleDateFormat("EEEE d MMMM yyyy"); //version 2
now.add(Calendar.DAY_OF_YEAR, day + 1); //Increments from test count + 1 due to count starting at 0 (would be today). Increments the date to get from today.
int DayOfWeek = now.get(Calendar.DAY_OF_WEEK);
boolean WorkingDayCheck = ((DayOfWeek >= Calendar.MONDAY) && (DayOfWeek <= Calendar.FRIDAY));
if(WorkingDayCheck) {
days[finalIndex++] = format.format(now.getTime());
return "\n(" + (finalIndex - 1) + ") " + String.valueOf(days[finalIndex - 1]);
} else {
now.add(Calendar.DATE, 2); //advance dates by two
dayCount = dayCount + 2; //Increase the day count by 2 to ensure that later dates are also incremented to avoid duplication i.e. Monday(Sat), Tuesday(Sun), Monday, Tuesday, Wed...
days[finalIndex++] = format.format(now.getTime());
return "\n(" + (finalIndex - 1) + ") " + String.valueOf(days[finalIndex - 1]);
}//END OF if else
}//END OF getDate4 method
I had to add and use an external dayCount (similar to the day int #Mohammed Osama used) separate from the count used in the mains methods iteration which I used previously to feed into this method and then when a weekend came up I incremented the date by 2 which is something I had experimented with before however the problem came when the weekend ended and it was back onto non weekend dates which ended up with:
Friday
Monday (previously Saturday)
Tuesday (previously Sunday)
Monday (weekend over, now back onto Monday) <--- Issue here and onwards
Tuesday
This is where the new dayCount came in which is now fed into this method simply as:
//Main method
//Iteration code start
getDate4(dayCount++);
//Iteration end
Incrementing this by 2 each time a weekend was encountered pushed the later dates to their appropriate position therefore now I am getting what I was always after being:
Friday
Monday (previously Saturday) <-Pushed ahead by 2 dates to Monday
Tuesday (previously Sunday) <-Pushed ahead by 2 dates to Tuesday
Wednesday (previously Monday) <-Pushed ahead 2 dates to Wednesday due to weekends incrementing the dayCount by 2
Thursday <--- etc. etc.
Thanks a lot for the help folks, can move on now finally :>

Difference between two dates?

Friends,
I am looking to calculate the difference in days.
Hey suppose if I enter 31st Aug 23:59:00 and next date 1 Sept 00:02:00 , I need to show the record as 1 day.
Please help me for this one.
Right now I am calculating the same using .getTimeInMillis() but it is not giving me expected results for the date condition mentioned above.
I you look for day and time difference then, use my code
public class AndroidWebImage extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Date sdate=Calendar.getInstance().getTime();
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
String setDate = "13/09/12 10:20:43";
Date AlarmDate=new Date(setDate);
String currentDate = format.format(sdate);
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(setDate);
d2 = format.parse(currentDate);
} catch (ParseException e) {
e.printStackTrace();
}
//Comparison
long diff = d1.getTime() - d2.getTime();
long diffSeconds = diff / 1000 % 60;
long days = (int) (diff / (1000 * 60 * 60 * 24));
long diffHours = (int) ((diff- (1000 * 60 * 60 * 24 * days)) / (1000 * 60 * 60));
long diffMinutes = (int) (diff- (1000 * 60 * 60 * 24 * days) - (1000 * 60 * 60 * diffHours))/ (1000 * 60);
int curhour=sdate.getHours();
int curmin=sdate.getMinutes();
int alarmhour=AlarmDate.getHours();
int alarmmin=AlarmDate.getMinutes();
if(curhour==alarmhour && curmin==alarmmin)
{
Toast.makeText(getApplicationContext(), String.valueOf(days+"days\n"+diffHours+"hrs"+diffMinutes+"min\n"+diffSeconds+"sec"),Toast.LENGTH_LONG).show();
}
else if(curhour>=alarmhour && curmin>=alarmmin || curhour<=alarmhour && curmin<=alarmmin)
{
Toast.makeText(getApplicationContext(), String.valueOf(days+"days\n"+diffHours+"hrs"+diffMinutes+"min\n"+diffSeconds+"sec"),Toast.LENGTH_LONG).show();
}
}
}
You can't do this with millis, because you need to know where the day boundary falls (i.e. midnight). A millisecond either side of midnight means two different days.
You need to use a Calendar to determine how many days lie within the interval between your two dates. The JodaTime library has a lot of additional support for this kind of calculation.
See also Calculating the difference between two Java date instances
Your're just trying to find the number of days, right?
Try looking at this, it might have what you are looking for.
i made this code before, its may helps you
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
* #author MErsan
*/
public class DateFormatter {
public static String formatDate(long time) {
StringBuilder result = new StringBuilder();
// 1- Check the year
// 2- Check the Month
// 3- Check the Day
// 4- Check the Hours
Date myDate = new Date(time);
Date todayDate = new Date(System.currentTimeMillis());
if (todayDate.getYear() - myDate.getYear() != 0) {
// Not same year, and should append the whole time
return DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT).format(myDate);
}
// Same Year
// now Check the month
if (todayDate.getMonth() - myDate.getMonth() != 0) {
return new SimpleDateFormat("MMM dd, hh:mm a").format(myDate);// Aug
// 16,
// 11:55
// PM
}
// Now Same Month
// Check the day
int daysDiff = todayDate.getDate() - myDate.getDate();
if (daysDiff == 1) {// Yesterday
result.append("Yesterday").append(' ');
result.append(new SimpleDateFormat("hh:mm a").format(myDate));
return result.toString();
} else if (daysDiff != 0) {
return new SimpleDateFormat("MMM dd, hh:mm a").format(myDate);// Aug
// 16,
// 11:55
// PM
}
// Same Day :')
// Check the hour
int hoursDiff = todayDate.getHours() - myDate.getHours();
if (hoursDiff < 0) {// Invalid Time
// :#
result.append("Today").append(' ');
result.append(new SimpleDateFormat("hh:mm a").format(myDate));
return result.toString();
} else if (hoursDiff > 3) {// Not Same Hour, Hour Diff more than 3 hours
result.append("Today").append(' ');
result.append(new SimpleDateFormat("hh:mm a").format(myDate));
return result.toString();
} else if (hoursDiff != 0) {// Hours Diff less than 3 hours, but not
// current hour
int mintuesDiff = todayDate.getMinutes() - myDate.getMinutes();
result.append("Before").append(' ');
result.append(hoursDiff).append(' ');
result.append("Hours").append(' ');
result.append("and").append(' ');
result.append(Math.abs(mintuesDiff)).append(' ');
result.append("Minutes");
System.err.println("Case 6");
return result.toString();
} else if (hoursDiff == 0) {// Same Hours
int mintuesDiff = todayDate.getMinutes() - myDate.getMinutes();
if (mintuesDiff < 1) {// Seconds Only {Same Minute}
int secondsDiff = todayDate.getSeconds() - myDate.getSeconds();
result.append("Before").append(' ');
result.append(Math.abs(secondsDiff)).append(' ');
result.append("Seconds");
return result.toString();
} else {
result.append("Before").append(' ');
result.append(Math.abs(mintuesDiff)).append(' ');
result.append("Minutes");
return result.toString();
}
}
// Default
return DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT).format(myDate);
}
}
import java.util.Calendar;
public class DateDifference
{
public static void main(String[] args)
{
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.set(2012, 01, 10);
calendar2.set(2012, 07, 01);
long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diffDays = diff / (24 * 60 * 60 * 1000);
System.out.println("Time in days: " + diffDays + " days.");
}
}
You need to get rid of the timestamps and then subtract dates to get the difference in dates or you can use Joda-time as below:
import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.Days;
Date past = new Date(112, 8, 1);
Date today = new Date(112, 7, 30);
int days = Days.daysBetween(new DateTime(past), new DateTime(today)).getDays();
Re-post:
There's a simple solution, that at least for me, is the only feasible solution.
The problem is that all the answers I see being tossed around - using Joda, or Calendar, or Date, or whatever - only take the amount of milliseconds into consideration. They end up counting the number of 24-hour cycles between two dates, rather than the actual number of days. So something from Jan 1st 11pm to Jan 2nd 1am will return 0 days.
To count the actual number of days between startDate and endDate, simply do:
// Find the sequential day from a date, essentially resetting time to start of the day
long startDay = startDate.getTime() / 1000 / 60 / 60 / 24;
long endDay = endDate.getTime() / 1000 / 60 / 60 / 24;
// Find the difference, duh
long daysBetween = endDay - startDay;
This will return "1" between Jan 2nd and Jan 1st. If you need to count the end day, just add 1 to daysBetween (I needed to do that in my code since I wanted to count the total number of days in the range).

Is there any library or algorithm for Persian (Shamsi or Jalali) calendar in Android? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
I want to convert Gregorian (western) date to Persian (Shamsi) date and vice versa for all versions of Android.
Is there any complete and reliable library or algorithm?
I'm using this algorithm for years and it is very accurate between 1901 and 2099.
Use it and Enjoy! :)
public class Utilities {
private class SolarCalendar {
public String strWeekDay = "";
public String strMonth = "";
int date;
int month;
int year;
public SolarCalendar()
{
Date MiladiDate = new Date();
calcSolarCalendar(MiladiDate);
}
public SolarCalendar(Date MiladiDate)
{
calcSolarCalendar(MiladiDate);
}
private void calcSolarCalendar(Date MiladiDate) {
int ld;
int miladiYear = MiladiDate.getYear() + 1900;
int miladiMonth = MiladiDate.getMonth() + 1;
int miladiDate = MiladiDate.getDate();
int WeekDay = MiladiDate.getDay();
int[] buf1 = new int[12];
int[] buf2 = new int[12];
buf1[0] = 0;
buf1[1] = 31;
buf1[2] = 59;
buf1[3] = 90;
buf1[4] = 120;
buf1[5] = 151;
buf1[6] = 181;
buf1[7] = 212;
buf1[8] = 243;
buf1[9] = 273;
buf1[10] = 304;
buf1[11] = 334;
buf2[0] = 0;
buf2[1] = 31;
buf2[2] = 60;
buf2[3] = 91;
buf2[4] = 121;
buf2[5] = 152;
buf2[6] = 182;
buf2[7] = 213;
buf2[8] = 244;
buf2[9] = 274;
buf2[10] = 305;
buf2[11] = 335;
if ((miladiYear % 4) != 0) {
date = buf1[miladiMonth - 1] + miladiDate;
if (date > 79) {
date = date - 79;
if (date <= 186) {
switch (date % 31) {
case 0:
month = date / 31;
date = 31;
break;
default:
month = (date / 31) + 1;
date = (date % 31);
break;
}
year = miladiYear - 621;
} else {
date = date - 186;
switch (date % 30) {
case 0:
month = (date / 30) + 6;
date = 30;
break;
default:
month = (date / 30) + 7;
date = (date % 30);
break;
}
year = miladiYear - 621;
}
} else {
if ((miladiYear > 1996) && (miladiYear % 4) == 1) {
ld = 11;
} else {
ld = 10;
}
date = date + ld;
switch (date % 30) {
case 0:
month = (date / 30) + 9;
date = 30;
break;
default:
month = (date / 30) + 10;
date = (date % 30);
break;
}
year = miladiYear - 622;
}
} else {
date = buf2[miladiMonth - 1] + miladiDate;
if (miladiYear >= 1996) {
ld = 79;
} else {
ld = 80;
}
if (date > ld) {
date = date - ld;
if (date <= 186) {
switch (date % 31) {
case 0:
month = (date / 31);
date = 31;
break;
default:
month = (date / 31) + 1;
date = (date % 31);
break;
}
year = miladiYear - 621;
} else {
date = date - 186;
switch (date % 30) {
case 0:
month = (date / 30) + 6;
date = 30;
break;
default:
month = (date / 30) + 7;
date = (date % 30);
break;
}
year = miladiYear - 621;
}
}
else {
date = date + 10;
switch (date % 30) {
case 0:
month = (date / 30) + 9;
date = 30;
break;
default:
month = (date / 30) + 10;
date = (date % 30);
break;
}
year = miladiYear - 622;
}
}
switch (month) {
case 1:
strMonth = "فروردين";
break;
case 2:
strMonth = "ارديبهشت";
break;
case 3:
strMonth = "خرداد";
break;
case 4:
strMonth = "تير";
break;
case 5:
strMonth = "مرداد";
break;
case 6:
strMonth = "شهريور";
break;
case 7:
strMonth = "مهر";
break;
case 8:
strMonth = "آبان";
break;
case 9:
strMonth = "آذر";
break;
case 10:
strMonth = "دي";
break;
case 11:
strMonth = "بهمن";
break;
case 12:
strMonth = "اسفند";
break;
}
switch (WeekDay) {
case 0:
strWeekDay = "يکشنبه";
break;
case 1:
strWeekDay = "دوشنبه";
break;
case 2:
strWeekDay = "سه شنبه";
break;
case 3:
strWeekDay = "چهارشنبه";
break;
case 4:
strWeekDay = "پنج شنبه";
break;
case 5:
strWeekDay = "جمعه";
break;
case 6:
strWeekDay = "شنبه";
break;
}
}
}
public static String getCurrentShamsidate() {
Locale loc = new Locale("en_US");
Utilities util = new Utilities();
SolarCalendar sc = util.new SolarCalendar();
return String.valueOf(sc.year) + "/" + String.format(loc, "%02d",
sc.month) + "/" + String.format(loc, "%02d", sc.date);
}
}
I think this java class is easier to use and more reliable.
I found it in Iranian forum, Iranians use Jalali Calendar and call it "Shamsi" that means Solar calendar. this is the Java class:
package MyUtil;
import java.util.Calendar;
import java.util.GregorianCalendar;
/**
* Title: Calender Conversion class
* Description: Convert Iranian (Jalali), Julian, and Gregorian dates to
* each other
* Public Methods Summary:
* -----------------------
* JavaSource_Calendar();
* JavaSource_Calendar(int year, int month, int day);
* int getIranianYear();
* int getIranianMonth();
* int getIranianDay();
* int getGregorianYear();
* int getGregorianMonth();
* int getGregorianDay();
* int getJulianYear();
* int getJulianMonth();
* int getJulianDay();
* String getIranianDate();
* String getGregorianDate();
* String getJulianDate();
* String getWeekDayStr();
* String toString();
* int getDayOfWeek();
* void nextDay();
* void nextDay(int days);
* void previousDay();
* void previousDay(int days);
* void setIranianDate(int year, int month, int day);
* void setGregorianDate(int year, int month, int day);
* void setJulianDate(int year, int month, int day);
*/
public class CalendarTool {
/**
* JavaSource_Calendar:
* The default constructor uses the current Gregorian date to initialize the
* other private memebers of the class (Iranian and Julian dates).
*/
public CalendarTool()
{
Calendar calendar = new GregorianCalendar();
setGregorianDate(calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH)+1,
calendar.get(Calendar.DAY_OF_MONTH));
}
/**
* JavaSource_Calendar:
* This constructor receives a Gregorian date and initializes the other private
* members of the class accordingly.
* #param year int
* #param month int
* #param day int
*/
public CalendarTool(int year, int month, int day)
{
setGregorianDate(year,month,day);
}
/**
* getIranianYear:
* Returns the 'year' part of the Iranian date.
* #return int
*/
public int getIranianYear() {
return irYear;
}
/**
* getIranianMonth:
* Returns the 'month' part of the Iranian date.
* #return int
*/
public int getIranianMonth() {
return irMonth;
}
/**
* getIranianDay:
* Returns the 'day' part of the Iranian date.
* #return int
*/
public int getIranianDay() {
return irDay;
}
/**
* getGregorianYear:
* Returns the 'year' part of the Gregorian date.
* #return int
*/
public int getGregorianYear() {
return gYear;
}
/**
* getGregorianMonth:
* Returns the 'month' part of the Gregorian date.
* #return int
*/
public int getGregorianMonth() {
return gMonth;
}
/**
* getGregorianDay:
* Returns the 'day' part of the Gregorian date.
* #return int
*/
public int getGregorianDay() {
return gDay;
}
/**
* getJulianYear:
* Returns the 'year' part of the Julian date.
* #return int
*/
public int getJulianYear() {
return juYear;
}
/**
* getJulianMonth:
* Returns the 'month' part of the Julian date.
* #return int
*/
public int getJulianMonth() {
return juMonth;
}
/**
* getJulianDay()
* Returns the 'day' part of the Julian date.
* #return int
*/
public int getJulianDay() {
return juDay;
}
/**
* getIranianDate:
* Returns a string version of Iranian date
* #return String
*/
public String getIranianDate()
{
return (irYear+"/"+irMonth+"/"+irDay);
}
/**
* getGregorianDate:
* Returns a string version of Gregorian date
* #return String
*/
public String getGregorianDate()
{
return (gYear+"/"+gMonth+"/"+gDay);
}
/**
* getJulianDate:
* Returns a string version of Julian date
* #return String
*/
public String getJulianDate()
{
return (juYear+"/"+juMonth+"/"+juDay);
}
/**
* getWeekDayStr:
* Returns the week day name.
* #return String
*/
public String getWeekDayStr()
{
String weekDayStr[]={
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"};
return (weekDayStr[getDayOfWeek()]);
}
/**
* toString:
* Overrides the default toString() method to return all dates.
* #return String
*/
public String toString()
{
return (getWeekDayStr()+
", Gregorian:["+getGregorianDate()+
"], Julian:["+getJulianDate()+
"], Iranian:["+getIranianDate()+"]");
}
/**
* getDayOfWeek:
* Returns the week day number. Monday=0..Sunday=6;
* #return int
*/
public int getDayOfWeek()
{
return (JDN % 7);
}
/**
* nextDay:
* Go to next julian day number (JDN) and adjusts the other dates.
*/
public void nextDay()
{
JDN++;
JDNToIranian();
JDNToJulian();
JDNToGregorian();
}
/**
* nextDay:
* Overload the nextDay() method to accept the number of days to go ahead and
* adjusts the other dates accordingly.
* #param days int
*/
public void nextDay(int days)
{
JDN+=days;
JDNToIranian();
JDNToJulian();
JDNToGregorian();
}
/**
* previousDay:
* Go to previous julian day number (JDN) and adjusts the otehr dates.
*/
public void previousDay()
{
JDN--;
JDNToIranian();
JDNToJulian();
JDNToGregorian();
}
/**
* previousDay:
* Overload the previousDay() method to accept the number of days to go backward
* and adjusts the other dates accordingly.
* #param days int
*/
public void previousDay(int days)
{
JDN-=days;
JDNToIranian();
JDNToJulian();
JDNToGregorian();
}
/**
* setIranianDate:
* Sets the date according to the Iranian calendar and adjusts the other dates.
* #param year int
* #param month int
* #param day int
*/
public void setIranianDate(int year, int month, int day)
{
irYear =year;
irMonth = month;
irDay = day;
JDN = IranianDateToJDN();
JDNToIranian();
JDNToJulian();
JDNToGregorian();
}
/**
* setGregorianDate:
* Sets the date according to the Gregorian calendar and adjusts the other dates.
* #param year int
* #param month int
* #param day int
*/
public void setGregorianDate(int year, int month, int day)
{
gYear = year;
gMonth = month;
gDay = day;
JDN = gregorianDateToJDN(year,month,day);
JDNToIranian();
JDNToJulian();
JDNToGregorian();
}
/**
* setJulianDate:
* Sets the date according to the Julian calendar and adjusts the other dates.
* #param year int
* #param month int
* #param day int
*/
public void setJulianDate(int year, int month, int day)
{
juYear = year;
juMonth = month;
juDay = day;
JDN = julianDateToJDN(year,month,day);
JDNToIranian();
JDNToJulian();
JDNToGregorian();
}
/**
* IranianCalendar:
* This method determines if the Iranian (Jalali) year is leap (366-day long)
* or is the common year (365 days), and finds the day in March (Gregorian
* Calendar)of the first day of the Iranian year ('irYear').Iranian year (irYear)
* ranges from (-61 to 3177).This method will set the following private data
* members as follows:
* leap: Number of years since the last leap year (0 to 4)
* Gy: Gregorian year of the begining of Iranian year
* march: The March day of Farvardin the 1st (first day of jaYear)
*/
private void IranianCalendar()
{
// Iranian years starting the 33-year rule
int Breaks[]=
{-61, 9, 38, 199, 426, 686, 756, 818,1111,1181,
1210,1635,2060,2097,2192,2262,2324,2394,2456,3178} ;
int jm,N,leapJ,leapG,jp,j,jump;
gYear = irYear + 621;
leapJ = -14;
jp = Breaks[0];
// Find the limiting years for the Iranian year 'irYear'
j=1;
do{
jm=Breaks[j];
jump = jm-jp;
if (irYear >= jm)
{
leapJ += (jump / 33 * 8 + (jump % 33) / 4);
jp = jm;
}
j++;
} while ((j<20) && (irYear >= jm));
N = irYear - jp;
// Find the number of leap years from AD 621 to the begining of the current
// Iranian year in the Iranian (Jalali) calendar
leapJ += (N/33 * 8 + ((N % 33) +3)/4);
if ( ((jump % 33) == 4 ) && ((jump-N)==4))
leapJ++;
// And the same in the Gregorian date of Farvardin the first
leapG = gYear/4 - ((gYear /100 + 1) * 3 / 4) - 150;
march = 20 + leapJ - leapG;
// Find how many years have passed since the last leap year
if ( (jump - N) < 6 )
N = N - jump + ((jump + 4)/33 * 33);
leap = (((N+1) % 33)-1) % 4;
if (leap == -1)
leap = 4;
}
/**
* IsLeap:
* This method determines if the Iranian (Jalali) year is leap (366-day long)
* or is the common year (365 days), and finds the day in March (Gregorian
* Calendar)of the first day of the Iranian year ('irYear').Iranian year (irYear)
* ranges from (-61 to 3177).This method will set the following private data
* members as follows:
* leap: Number of years since the last leap year (0 to 4)
* Gy: Gregorian year of the begining of Iranian year
* march: The March day of Farvardin the 1st (first day of jaYear)
*/
public boolean IsLeap(int irYear1)
{
// Iranian years starting the 33-year rule
int Breaks[]=
{-61, 9, 38, 199, 426, 686, 756, 818,1111,1181,
1210,1635,2060,2097,2192,2262,2324,2394,2456,3178} ;
int jm,N,leapJ,leapG,jp,j,jump;
gYear = irYear1 + 621;
leapJ = -14;
jp = Breaks[0];
// Find the limiting years for the Iranian year 'irYear'
j=1;
do{
jm=Breaks[j];
jump = jm-jp;
if (irYear1 >= jm)
{
leapJ += (jump / 33 * 8 + (jump % 33) / 4);
jp = jm;
}
j++;
} while ((j<20) && (irYear1 >= jm));
N = irYear1 - jp;
// Find the number of leap years from AD 621 to the begining of the current
// Iranian year in the Iranian (Jalali) calendar
leapJ += (N/33 * 8 + ((N % 33) +3)/4);
if ( ((jump % 33) == 4 ) && ((jump-N)==4))
leapJ++;
// And the same in the Gregorian date of Farvardin the first
leapG = gYear/4 - ((gYear /100 + 1) * 3 / 4) - 150;
march = 20 + leapJ - leapG;
// Find how many years have passed since the last leap year
if ( (jump - N) < 6 )
N = N - jump + ((jump + 4)/33 * 33);
leap = (((N+1) % 33)-1) % 4;
if (leap == -1)
leap = 4;
if (leap==4 || leap==0)
return true;
else
return false;
}
/**
* IranianDateToJDN:
* Converts a date of the Iranian calendar to the Julian Day Number. It first
* invokes the 'IranianCalender' private method to convert the Iranian date to
* Gregorian date and then returns the Julian Day Number based on the Gregorian
* date. The Iranian date is obtained from 'irYear'(1-3100),'irMonth'(1-12) and
* 'irDay'(1-29/31).
* #return long (Julian Day Number)
*/
private int IranianDateToJDN()
{
IranianCalendar();
return (gregorianDateToJDN(gYear,3,march)+ (irMonth-1) * 31 - irMonth/7 * (irMonth-7) + irDay -1);
}
/**
* JDNToIranian:
* Converts the current value of 'JDN' Julian Day Number to a date in the
* Iranian calendar. The caller should make sure that the current value of
* 'JDN' is set correctly. This method first converts the JDN to Gregorian
* calendar and then to Iranian calendar.
*/
private void JDNToIranian()
{
JDNToGregorian();
irYear = gYear - 621;
IranianCalendar(); // This invocation will update 'leap' and 'march'
int JDN1F = gregorianDateToJDN(gYear,3,march);
int k = JDN - JDN1F;
if (k >= 0)
{
if (k <= 185)
{
irMonth = 1 + k/31;
irDay = (k % 31) + 1;
return;
}
else
k -= 186;
}
else
{
irYear--;
k += 179;
if (leap == 1)
k++;
}
irMonth = 7 + k/30;
irDay = (k % 30) + 1;
}
/**
* julianDateToJDN:
* Calculates the julian day number (JDN) from Julian calendar dates. This
* integer number corresponds to the noon of the date (i.e. 12 hours of
* Universal Time). This method was tested to be good (valid) since 1 March,
* -100100 (of both calendars) up to a few millions (10^6) years into the
* future. The algorithm is based on D.A.Hatcher, Q.Jl.R.Astron.Soc. 25(1984),
* 53-55 slightly modified by K.M. Borkowski, Post.Astron. 25(1987), 275-279.
* #param year int
* #param month int
* #param day int
* #return int
*/
private int julianDateToJDN(int year, int month, int day)
{
return (year + (month - 8) / 6 + 100100) * 1461/4 + (153 * ((month+9) % 12) + 2)/5 + day - 34840408;
}
/**
* JDNToJulian:
* Calculates Julian calendar dates from the julian day number (JDN) for the
* period since JDN=-34839655 (i.e. the year -100100 of both calendars) to
* some millions (10^6) years ahead of the present. The algorithm is based on
* D.A. Hatcher, Q.Jl.R.Astron.Soc. 25(1984), 53-55 slightly modified by K.M.
* Borkowski, Post.Astron. 25(1987), 275-279).
*/
private void JDNToJulian()
{
int j= 4 * JDN + 139361631;
int i= ((j % 1461)/4) * 5 + 308;
juDay = (i % 153) / 5 + 1;
juMonth = ((i/153) % 12) + 1;
juYear = j/1461 - 100100 + (8-juMonth)/6;
}
/**
* gergorianDateToJDN:
* Calculates the julian day number (JDN) from Gregorian calendar dates. This
* integer number corresponds to the noon of the date (i.e. 12 hours of
* Universal Time). This method was tested to be good (valid) since 1 March,
* -100100 (of both calendars) up to a few millions (10^6) years into the
* future. The algorithm is based on D.A.Hatcher, Q.Jl.R.Astron.Soc. 25(1984),
* 53-55 slightly modified by K.M. Borkowski, Post.Astron. 25(1987), 275-279.
* #param year int
* #param month int
* #param day int
* #return int
*/
private int gregorianDateToJDN(int year, int month, int day)
{
int jdn = (year + (month - 8) / 6 + 100100) * 1461/4 + (153 * ((month+9) % 12) + 2)/5 + day - 34840408;
jdn = jdn - (year + 100100+(month-8)/6)/100*3/4+752;
return (jdn);
}
/**
* JDNToGregorian:
* Calculates Gregorian calendar dates from the julian day number (JDN) for
* the period since JDN=-34839655 (i.e. the year -100100 of both calendars) to
* some millions (10^6) years ahead of the present. The algorithm is based on
* D.A. Hatcher, Q.Jl.R.Astron.Soc. 25(1984), 53-55 slightly modified by K.M.
* Borkowski, Post.Astron. 25(1987), 275-279).
*/
private void JDNToGregorian()
{
int j= 4 * JDN + 139361631;
j = j + (((((4* JDN +183187720)/146097)*3)/4)*4-3908);
int i= ((j % 1461)/4) * 5 + 308;
gDay = (i % 153) / 5 + 1;
gMonth = ((i/153) % 12) + 1;
gYear = j/1461 - 100100 + (8-gMonth)/6;
}
private int irYear; // Year part of a Iranian date
private int irMonth; // Month part of a Iranian date
private int irDay; // Day part of a Iranian date
private int gYear; // Year part of a Gregorian date
private int gMonth; // Month part of a Gregorian date
private int gDay; // Day part of a Gregorian date
private int juYear; // Year part of a Julian date
private int juMonth; // Month part of a Julian date
private int juDay; // Day part of a Julian date
private int leap; // Number of years since the last leap year (0 to 4)
private int JDN; // Julian Day Number
private int march; // The march day of Farvardin the first (First day of jaYear)
} // End of Class 'JavaSource_Calendar
You can easily set the Gregorian Day, Month and Year, then call "getIranianDate()" method to get the date in string format, just like the sample code below:
MyUtil.CalendarTool ct = new CalendarTool(2012,10,10);
System.out.println(ct.getIranianDate());
I hope it helps.
Use IBM's International Components for Unicode (icu4j). It is part of Unicode Consortium, is extremely reliable and can be used in any java project (Java EE, Java SE, Android, etc). Use it with Gradle, Maven or simply by downloading the jar.
TL;DR
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.ULocale;
public class DateTimeUtils {
public static final ULocale PERSIAN_LOCALE = new ULocale("fa_IR#calendar=persian");
public static final ULocale PERSIAN_EN_LOCALE = new ULocale("en#calendar=persian");
public static final ZoneId IRAN_ZONE_ID = ZoneId.of("Asia/Tehran");
public static Calendar fromDateToPersianCalendar(Date date) {
Calendar persianCalendar = Calendar.getInstance(PERSIAN_LOCALE);
persianCalendar.clear();
persianCalendar.setTime(date);
return persianCalendar;
}
/**
* #param date
* #param field example: Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, etc
*/
public static int fromDateToPersianCalendarField(Date date, int field) {
return fromDateToPersianCalendar(date).get(field);
}
public static String fromDateToPersianString(Date date) {
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, PERSIAN_LOCALE);
return df.format(date);
}
public static String fromDateToPersianString(Date date, String pattern) {
return new SimpleDateFormat(pattern, PERSIAN_LOCALE).format(date);
}
public static String fromDateToPersianString(Date date, String pattern, ULocale locale) {
return new SimpleDateFormat(pattern, locale).format(date);
}
/**
* #param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
*/
public static Date fromPersianDateToDate(int year, int month, int day, int hour, int minutes, int seconds) {
return new Date(fromPersianDate(year, month, day, hour, minutes, seconds));
}
/**
* #param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
*/
public static String fromPersianDateToPersianString(int year, int month, int day, int hour, int minutes, int seconds) {
return fromDateToPersianString(fromPersianDateToDate(year, month, day, hour, minutes, seconds));
}
/**
* #param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
*/
public static LocalDateTime fromPersianDateToLocalDateTime(int year, int month, int day, int hour, int minutes, int seconds) {
return fromPersianDateToZonedDateTime(year, month, day, hour, minutes, seconds).toLocalDateTime();
}
/**
* #param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
*/
public static ZonedDateTime fromPersianDateToZonedDateTime(int year, int month, int day, int hour, int minutes, int seconds) {
return toZonedDateTime(fromPersianDate(year, month, day, hour, minutes, seconds));
}
/**
* #param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
*/
public static long fromPersianDate(int year, int month, int day, int hour, int minutes, int seconds) {
Calendar persianCalendar = Calendar.getInstance(PERSIAN_LOCALE);
persianCalendar.clear();
persianCalendar.set(year, month, day, hour, minutes, seconds);
return persianCalendar.getTimeInMillis();
}
public static ZonedDateTime toZonedDateTime(Long epochMilli) {
if(epochMilli == null) return null;
return Instant.ofEpochMilli(epochMilli).atZone(IRAN_ZONE_ID);
}
}
Usage:
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.Date;
import com.ibm.icu.util.Calendar;
public class DateTimeUtilsTest {
public static void main(String[] args) {
System.out.println("Java 7 and before:");
Date date = new Date(1467262800000L);
System.out.println("Converting Gregorian date to Persian:");
Calendar persianCalendar = DateTimeUtils.fromDateToPersianCalendar(date);
System.out.println(persianCalendar.get(Calendar.YEAR));
System.out.println(persianCalendar.get(Calendar.MONTH));
System.out.println(persianCalendar.get(Calendar.DAY_OF_MONTH));
System.out.println(DateTimeUtils.fromDateToPersianString(persianCalendar.getTime()));
System.out.println("\nAdding 1 month and 5 days:");
persianCalendar.add(Calendar.MONTH, 1); // add a month
persianCalendar.add(Calendar.DAY_OF_MONTH, 5); // add 5 days
System.out.println(persianCalendar.get(Calendar.YEAR));
System.out.println(persianCalendar.get(Calendar.MONTH));
System.out.println(persianCalendar.get(Calendar.DAY_OF_MONTH));
System.out.println(DateTimeUtils.fromDateToPersianString(persianCalendar.getTime()));
System.out.println("\nConverting Persian date to Gregorian:");
Date gregorianDate = DateTimeUtils.fromPersianDateToDate(1395, 3, 10, 9, 30, 0);
System.out.println(gregorianDate);
System.out.println(DateTimeUtils.fromDateToPersianString(gregorianDate)); // to Persian string
System.out.println(DateTimeUtils.fromDateToPersianString(gregorianDate, "dd/MM/yy - H:mm:dd")); // to Persian string with custom format
System.out.println(DateTimeUtils.fromDateToPersianString(gregorianDate, "dd/MM/yy - H:mm:dd" , DateTimeUtils.PERSIAN_EN_LOCALE)); // to Persian string with custom format and Latin characters
System.out.println("\n"+"Java 8 onward:");
ZonedDateTime gregorianZonedDateTime = DateTimeUtils.fromPersianDateToZonedDateTime(1395, 3, 10, 9, 30, 0);
System.out.println(gregorianZonedDateTime);
LocalDateTime gregorianLocalDateTime = DateTimeUtils.fromPersianDateToLocalDateTime(1395, 3, 10, 9, 30, 0);
System.out.println(gregorianLocalDateTime);
}
}
Output:
Java 7 and before:
Converting Gregorian date to Persian:
1395
3
10
۱۳۹۵ تیر ۱۰, پنجشنبه
Adding 1 month and 5 days:
1395
4
15
۱۳۹۵ مرداد ۱۵, جمعه
Converting Persian date to Gregorian:
Thu Jun 30 09:30:00 IRDT 2016
۱۳۹۵ تیر ۱۰, پنجشنبه
۱۰/۰۴/۹۵ - ۹:۳۰:۱۰
10/04/95 - 9:30:10
Java 8 onward:
2016-06-30T09:30+04:30[Asia/Tehran]
2016-06-30T09:30
More detailed:
Java 7 and before:
You can expect all of functionalities of java.util.Calendar in addition to some other ones:
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.ULocale;
...
ULocale locale = new ULocale("fa_IR#calendar=persian");
Calendar persianCalendar = Calendar.getInstance(locale);
persianCalendar.clear();
persianCalendar.set(1395, 3, 10); // Tir(4th month) 10th 1395 equivalent to June 30th 2016
java.util.Date gregorianDate = persianCalendar.getTime();
System.out.println(gregorianDate); // Thu Jun 30 00:00:00 IDT 2016
// Gregorian to Persian
java.util.Calendar gregorianCal = java.util.GregorianCalendar.getInstance();
gregorianCal.set(2016, java.util.Calendar.JUNE, 30);
persianCalendar.setTime(gregorianCal.getTime());
System.out.println(persianCalendar.get(Calendar.YEAR)); // 1395
System.out.println(persianCalendar.get(Calendar.MONTH)); // 3
System.out.println(persianCalendar.get(Calendar.DAY_OF_MONTH)); // 10
WARNING: Note that month field is zero based in Java calendar so by calendar.set(1395, 3, 10) calendar will represent 4th month of 1395, not 3rd!
If you need text outputs in persian:
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.SimpleDateFormat;
...
// full date output in persian
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, locale);
System.out.println(df.format(persianCalendar.getTime()));
// year output in persian
SimpleDateFormat sdf1 = new SimpleDateFormat(SimpleDateFormat.YEAR, locale);
System.out.println(sdf1.format(persianCalendar.getTime()));
// month name output in persian
SimpleDateFormat sdf2 = new SimpleDateFormat(SimpleDateFormat.MONTH, locale);
System.out.println(sdf2.format(persianCalendar.getTime()));
// weekday name output in persian
SimpleDateFormat sdf3 = new SimpleDateFormat(SimpleDateFormat.WEEKDAY, locale);
System.out.println(sdf3.format(persianCalendar.getTime()));
// full date output in YY/MM/dd form
SimpleDateFormat sdf4 = new SimpleDateFormat("YY/MM/dd", locale);
System.out.println(sdf4.format(persianCalendar.getTime()));
Output:
ه‍.ش. ۱۳۹۵ تیر ۱۰, پنجشنبه
۱۳۹۵
تیر
پنجشنبه
۹۵/۰۴/۱۰
If you need output to be in english, change new ULocale("fa_IR#calendar=persian") to new ULocale("en#calendar=persian").
Output:
AP 1395 Tir 10, Thu
1395
Tir
Thu
95/04/10
Other nice things:
// Get number of days in month
System.out.println(persianCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); // 31
// Get first day of week
System.out.println(persianCalendar.getFirstDayOfWeek()); // 7 (Saturday according to docs)
// Add some amount of time
persianCalendar.add(Calendar.MONTH, 2);
System.out.println(persianCalendar.get(Calendar.YEAR)); //1395
System.out.println(persianCalendar.get(Calendar.MONTH)); // 5
System.out.println(persianCalendar.get(Calendar.DAY_OF_MONTH)); // 10
For other functionalities see icu4j demos, specially:
demo of various calendar fields
list of Tuesdays and Thursdays of current year
demo of converting number to text representation (use fa_IR for locale)
Also see Calendar and PersianCalendar API.
Java 8 onward:
In order to use java.time classes like ZonedDateTime or LocalDateTime, you could simply use this methods to convert a persian date to preferred classes:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.ULocale;
...
public static LocalDateTime fromPersianDateToLocalDateTime(int year, int month, int day, int hour, int minutes, int seconds) {
return fromPersianDateToZonedDateTime(year, month, day, hour, minutes, seconds).toLocalDateTime();
}
public static ZonedDateTime fromPersianDateToZonedDateTime(int year, int month, int day, int hour, int minutes, int seconds) {
return toZonedDateTime(fromPersianDate(year, month, day, hour, minutes, seconds));
}
public static long fromPersianDate(int year, int month, int day, int hour, int minutes, int seconds) {
Calendar persianCalendar = Calendar.getInstance(new ULocale("fa_IR#calendar=persian"));
persianCalendar.clear();
persianCalendar.set(year, month, day, hour, minutes, seconds);
return persianCalendar.getTimeInMillis();
}
public static ZonedDateTime toZonedDateTime(Long epochMilli) {
if(epochMilli == null) return null;
return Instant.ofEpochMilli(epochMilli).atZone(ZoneId.of("Asia/Tehran"));
}
Remarks About Jar Size
If you're concerned about icu4j's jar size , then you may rebuild it and just use the Calendar module (2,176KB). More Info: ver. 57 or earlier , ver. 58 or later using ICU Data Build Tool.
this method is very exact and simply also support leap years
Explain:
step 1:
time today is contain current time
step 2:
create two array for gregorian and jalali day in months(g_days_in_month&j_days_in_month)
step 3:
create variable for retention difference time between calendars
(gy,gm,gd)
and variable g_day_no for days of years.
step 4:
insert day of month and collect with days.
step 5:
convert days of years to jalili years (jy)
at the end :
set jalali month from day number,
set jalali day from jalali day of month array.
good luck.
Time today = new Time(Time.getCurrentTimezone());
today.setToNow();
int Day = (today.monthDay); // Day of the month (0-31)
int Month = (today.month); // Month (0-11)
int Year = (today.year); // Year
String persianDate = GregorianToJalali(Year, Month+1, Day);
private String GregorianToJalali(int g_y, int g_m, int g_d)
{
int[] g_days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int[] j_days_in_month = {31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29};
int gy = g_y-1600;
int gm = g_m-1;
int gd = g_d-1;
int g_day_no = 365*gy+div(gy+3,4)-div(gy+99,100)+div(gy+399,400);
for (int i=0; i < gm; ++i)
g_day_no += g_days_in_month[i];
if (gm>1 && ((gy%4==0 && gy%100!=0) || (gy%400==0)))
// leap and after Feb
g_day_no++;
g_day_no += gd;
int j_day_no = g_day_no-79;
int j_np = div(j_day_no, 12053); //12053 = 365*33 + 32/4
j_day_no = j_day_no % 12053;
int jy = 979+33*j_np+4*div(j_day_no,1461); // 1461 = 365*4 + 4/4
j_day_no %= 1461;
if (j_day_no >= 366) {
jy += div(j_day_no-1, 365);
j_day_no = (j_day_no-1)%365;
}
int j;
for (j=0; j < 11 && j_day_no >= j_days_in_month[j]; ++j)
j_day_no -= j_days_in_month[j];
int jm = j+1;
int jd = j_day_no+1;
String Result= jy+"/"+jm+"/"+jd;
return (Result);
}
private int div(float a, float b)
{
return (int)(a/b);
}
The newest version v3.10-2015g of my library Time4A (an Android adaptation of Time4J) contains support for the Jalali calendar. The library deploys the algorithm of Borkowski (valid until gregorian year 2129). Actually about 25 languages are supported for Persian months and eras (including Farsi and Pashto, based on CLDR-28).
Examples of usage:
// current date
PersianCalendar jalali = SystemClock.inLocalView().now(PersianCalendar.axis());
System.out.println(jalali); // AP-1394-08-04
// tomorrow
jalali = jalali.plus(CalendarDays.ONE);
System.out.println(jalali); // AP-1394-08-05
// localized format of tomorrow (English and Farsi)
ChronoFormatter<PersianCalendar> f =
ChronoFormatter.ofStyle(DisplayMode.FULL, Locale.ENGLISH, PersianCalendar.axis());
Locale farsi = new Locale("fa");
System.out.println(f.format(jalali)); // Tuesday, Aban 5, 1394 AP
System.out.println(f.with(farsi).format(jalali)); // سه‌شنبه, آبان 5, 1394 ه‍.ش.
// shift back to month Farvardin and format the result
jalali = jalali.with(PersianCalendar.MONTH_OF_YEAR, PersianMonth.FARVARDIN);
System.out.println(f.format(jalali)); // Wednesday, Farvardin 5, 1394 AP
System.out.println(f.with(farsi).format(jalali)); // چهارشنبه, فروردین 5, 1394 ه‍.ش.
// conversion to gregorian date
System.out.println(jalali); // AP-1394-01-05
System.out.println(jalali.transform(PlainDate.class)); // 2015-03-25
// create new year in persian calendar and show gregorian counter part
jalali = PersianCalendar.of(1394, PersianMonth.FARVARDIN, 1);
System.out.println(jalali.transform(PlainDate.class)); // 2015-03-21
// create new year in gregorian calendar and show persian counter part
PlainDate gregorianDate = PlainDate.of(2015, Month.JANUARY, 1);
System.out.println(gregorianDate.transform(PersianCalendar.class)); // AP-1393-10-11
// delta between gregorian new year and persian new year
System.out.println(CalendarDays.between(gregorianDate, jalali).getAmount()); // 79
Interoperability with java.util.Date on Android
Since Time4A manages its own set of immutable types and is not based on the primary temporal type of Android, I show following bridge:
// Time4A => Android
PlainDate gdate = jalali.transform(PlainDate.class);
Moment m1 = gdate.atStartOfDay().inTimezone(ASIA.TEHRAN);
java.util.Date jud = TemporalType.JAVA_UTIL_DATE.from(m1);
// Android => Time4A
java.util.Date input = new java.util.Date();
Moment m2 = TemporalType.JAVA_UTIL_DATE.translate(input);
jalali = m2.toZonalTimestamp(ASIA.TEHRAN).toDate().transform(PersianCalendar.class);
Try this
import java.util.Calendar;
import java.util.Date;
public class PersianCalendar {
String[] weekDayNames = {
"شنبه","یکشنبه","دوشنبه",
"سه شنبه", "چهارشنبه",
"پنج شنبه", "جمعه"
};
String[] monthNames ={
"فروردین","اردیبهشت","خرداد","تیر", "مرداد","شهریور",
"مهر", "آبان", "آذر","دی", "بهمن","اسفند"
};
String strWeekDay = "";
String strMonth = "";
int day;
int month;
int year;
int ld;
Calendar calendar = Calendar.getInstance();
int gregorianYear =calendar.get(Calendar.YEAR);
int gregorianMonth = calendar.get(Calendar.MONTH)+1;
int gregorianDate = calendar.get(Calendar.DATE);
int WeekDay = calendar.get(Calendar.DAY_OF_WEEK);
int[] buf1 = {0,31,59,90,120,151,181,212,243,273,304,334};
int[] buf2 = {0,31,60, 91,121,152,182, 213, 244, 274,305,335};
public PersianCalendar(){
Date gregorianDate = new Date();
calendar.setTime(gregorianDate);
toPersian(gregorianDate);
}
public PersianCalendar(Date gregorianDate){
calendar.setTime(gregorianDate);
toPersian(gregorianDate);
}
private void toPersian(Date gregorianDate)
{
if ((gregorianYear % 4) != 0)
func1();
else
func2();
strMonth = monthNames[month-1];
strWeekDay = weekDayNames[WeekDay];
}
private void func1()
{
day = buf1[gregorianMonth - 1] + gregorianDate;
if (day > 79){
day = day - 79;
if (day <= 186) {
int day2 = day;
month = (day2 / 31) + 1;
day = (day2 % 31);
if(day2 % 31 == 0){
month--;
day = 31;
}
year = gregorianYear - 621;
}
else {
int day2 = day - 186;
month = (day2 / 30) + 7;
day = (day2 % 30);
if(day2 % 30 == 0){
month = (day2 / 30) + 6;
day = 30;
}
year = gregorianYear - 621;
}
}
else{
ld = gregorianYear > 1996 && gregorianYear % 4 == 1 ? 11 : 10 ;
int day2 = day + ld;
month = (day2 / 30) + 10;
day = (day2 % 30);
if(day2 % 30 == 0) {
month--;
day = 30;
}
year = gregorianYear - 622;
}
}
private void func2()
{
day = buf2[gregorianMonth - 1] + gregorianDate;
ld = gregorianYear >= 1996 ? 79 : 80 ;
if (day > ld) {
day = day - ld;
if (day <= 186) {
int day2 = day;
month = (day2 / 31) + 1;
day = (day2 % 31);
if(day2 % 31 == 0){
month--;
day = 31;
}
year = gregorianYear - 621;
} else {
int day2 = day - 186;
month = (day2 / 30) + 7;
day = (day2 % 30);
if(day2 % 30 == 0 ){
month--;
day = 30;
}
year = gregorianYear - 621;
}
}
else {
int day2 = day + 10;
month = (day2 / 30) + 10;
day = (day2 % 30);
if(day2 % 30==0){
month--;
day = 30;
}
year = gregorianYear - 622;
}
}
}
create instance
PersianCalendar sc = new PersianCalendar();
String s= sc.strWeekDay + " " +sc.day + " " +
sc.strMonth + " " + sc.year;
System.out.print(s);
//setTitle(s);
There is persianutils project which includes a bi-directional DateConverter; Gregorian <-> Persian (Jalali). It is written in Scala, so I suppose using it in a Java project would be quite easy.
The algorithm used is valid for Gregorian years up to ~3790 and Persian years up to ~3170.
DISCLAIMER: I am the author of PersianUtils
You may use this stable and tested library with a formatter class, Roozh for Java. It's not deprecated and always getting updated with cool features which Persian date time needs.
I have developed Android Shamsi datepicker widget with hijri - gerogian- shamsi event view:
https://github.com/irshst/ir.shes.calendar
Create the calculateJalaliDate as function like so;
and then return the Jalali date in String
public String calculateJalaliDate(){
Calendar c = Calendar.getInstance();
String jalaliDate,JalaliMonth;
int jalaliYear,jalaliMonth,calculateMonth,jalaliDay=0,allDays=0;
int day=c.get(Calendar.DAY_OF_MONTH);
int month=c.get(Calendar.MONTH)+1;
int year=c.get(Calendar.YEAR);
switch (month){
case 1: allDays=year*365+31+day;break;
case 2: allDays=year*365+(31+28)+day;break;
case 3: allDays=year*365+(31+28+31)+day;break;
case 4: allDays=year*365+(31+28+31+30)+day;break;
case 5: allDays=year*365+(31+28+31+30+31)+day;break;
case 6: allDays=year*365+(31+28+31+30+31+30)+day;break;
case 7: allDays=year*365+(31+28+31+30+31+30+31)+day;break;
case 8: allDays=year*365+(31+28+31+30+31+30+31+31)+day;break;
case 9: allDays=year*365+(31+28+31+30+31+30+31+31+30)+day;break;
case 10: allDays=year*365+(31+28+31+30+31+30+31+31+30+31)+day;break;
case 11: allDays=year*365+(31+28+31+30+31+30+31+31+30+31+30)+day;break;
case 12: allDays=year*365+(31+28+31+30+31+30+31+31+30+31+30+31)+day;break;
}
//226899
jalaliYear=( allDays - 227139 )/365+1;
calculateMonth=( allDays - 227139 )%365;
if(calculateMonth<32)jalaliMonth=1;
else if((calculateMonth-31)<32){jalaliMonth=2;jalaliDay=calculateMonth-31;}
else if((calculateMonth-62)<32){jalaliMonth=3;jalaliDay=calculateMonth-62;}
else if((calculateMonth-93)<32){jalaliMonth=4;jalaliDay=calculateMonth-93;}
else if((calculateMonth-124)<32){jalaliMonth=5;jalaliDay=calculateMonth-124;}
else if((calculateMonth-155)<32){jalaliMonth=6;jalaliDay=calculateMonth-155;}
else if((calculateMonth-186)<31){jalaliMonth=7;jalaliDay=calculateMonth-186;}
else if((calculateMonth-216)<31){jalaliMonth=8;jalaliDay=calculateMonth-216;}
else if((calculateMonth-246)<31){jalaliMonth=9;jalaliDay=calculateMonth-246;}
else if((calculateMonth-276)<31){jalaliMonth=10;jalaliDay=calculateMonth-276;}
else if((calculateMonth-306)<31){jalaliMonth=11;jalaliDay=calculateMonth-306;}
else {
jalaliMonth=12;
if((jalaliYear%4)==0)jalaliDay=calculateMonth-336;
else jalaliDay=calculateMonth-335;
}
/*switch (jalaliMonth){
case 1:JalaliMonth="فروردین"; break;
case 2:JalaliMonth="اردیبهشت"; break;
case 3:JalaliMonth="خرداد"; break;
case 4:JalaliMonth="تیر"; break;
case 5:JalaliMonth="مرداد"; break;
case 6:JalaliMonth="شهریور"; break;
case 7:JalaliMonth="مهر"; break;
case 8:JalaliMonth="آبان"; break;
case 9:JalaliMonth="آذر"; break;
case 10:JalaliMonth="دی"; break;
case 11:JalaliMonth="بهمن"; break;
case 12:JalaliMonth="اسفند"; break;
}*/
jalaliDate=String.valueOf(jalaliYear)+"/"+String.valueOf(jalaliMonth)+"/"+String.valueOf(jalaliDay);
return jalaliDate;
}
Beside Time4A, icu4j, which are too heavy libraries, I written a class to handle Persian calendar accurately and you can find it here:
https://github.com/hadilq/java-persian-calendar/blob/master/persian/src/main/java/ir/hadilq/PersianCalendar.java
As you can find it in its tests, this class supports from year 3000 before hijra to 3000 after hijra.

Calculating dates given two dates excluding weekend

I am using Joda time api in a Spring 3.0 project for to calculate dates. Now I have a start and end date and I want to get everyday exept weekend or Saturday or Sunday between these two dates. How can I achieve this ?
I looked at this post Joda time - all mondays between two dates.
It offered some guidance but still vague as how to exclude two dates.
I assume your question is how to
get every day except weekend or Saturday or Sunday between two dates.
Solution :
public static void main(String[] args) {
final LocalDate start = LocalDate.now();
final LocalDate end = new LocalDate(2012, 1, 14);
LocalDate weekday = start;
if (start.getDayOfWeek() == DateTimeConstants.SATURDAY ||
start.getDayOfWeek() == DateTimeConstants.SUNDAY) {
weekday = weekday.plusWeeks(1).withDayOfWeek(DateTimeConstants.MONDAY);
}
while (weekday.isBefore(end)) {
System.out.println(weekday);
if (weekday.getDayOfWeek() == DateTimeConstants.FRIDAY)
weekday = weekday.plusDays(3);
else
weekday = weekday.plusDays(1);
}
}
I'm new here.
I've been looking for a solution to this problem and that did not use loop but have not found a suitable algorithm. So I decided to create this solution does not use loop, very efficient and the code has been tested.
public int betweenDaysIgnoreWeekends(DateTime startDate, DateTime endDate) {
//Um numero que representa o dia da semana para a data final, exemplo segunda=1, terça=2, quarta=3...
int dayOfWeekEndDateNumber = Integer.valueOf(endDate.dayOfWeek()
.getAsString());
//Um numero que representa o dia da semana para a data inicial, exemplo segunda=1, terça=2, quarta=3...
int dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek()
.getAsString());
//Se a data final for sabado ou domingo, finja ser sexta-feira
if (dayOfWeekEndDateNumber == 6 || dayOfWeekEndDateNumber == 7) {
int DaysToAdd = 8 - dayOfWeekEndDateNumber;
endDate = endDate.plusDays(DaysToAdd);
dayOfWeekEndDateNumber = Integer.valueOf(endDate.dayOfWeek()
.getAsString());
}
//Se a data inicial for sabado ou domingo, finja ser segunda-feira
if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
int DaysToAdd = 8 - dayOfWeekStartDateNumber;
startDate = startDate.plusDays(DaysToAdd);
dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek()
.getAsString());
}
//Quantos dias se passaram contando os fins de semana
int days = Days.daysBetween(startDate, endDate).getDays();
//Quantas semanas se passaram exatamente
int weeks = days / 7;
//O excesso de dias que sobrou, exemplo: 1 semana e 3 dias o excess=3 e weeks=1
int excess = days % 7;
//Se a data inicial for igual a data final, passou 0 dia
if (startDate.equals(endDate)) {
return 0;
} else {
//O excesso de dias passou pelo fim de semana, então deve-se retirar 2 dias
//da quantidade final de dias
if (excess + dayOfWeekStartDateNumber >= 6) {
//Quantidade de semanas * 5 dias uteis + o excesso de dias - o final de semana que o excesso atravessou
return weeks * 5 + excess - 2;
}
//Quantidade de semanas * 5 dias uteis + o excesso de dias
return weeks * 5 + excess;
}
}
I have been using #Josh Maag's logic for almost a year now but recently found that it returns wrong value when endDate happens to fall on a Saturday.
Here is the version I would like to share which considers to subtract days from endDate when it happens to be a Saturday or a Sunday.
public static int getDaysBetweenIgnoreWeekends(org.joda.time.DateTime startDate, org.joda.time.DateTime endDate, boolean ignoreTimeOfDay) {
// If the start date is equal to the closing date, spent 0 days
if (startDate.equals(endDate))
return 0;
if (ignoreTimeOfDay && startDate.toLocalDate().equals(endDate.toLocalDate()))
return 0;
// A number that represents the day for the start date, Monday = 1 , Tuesday = 2 , Wednesday = 3 ...
int dayOfWeekStartDateNumber = startDate.getDayOfWeek();
int dayOfWeekEndDateNumber = endDate.getDayOfWeek();
// If the starting date is Saturday or Sunday , pretend to be Monday
if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
int DaysToAdd = 8 - dayOfWeekStartDateNumber;
startDate = startDate.plusDays(DaysToAdd);
dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek().getAsString());
}
org.joda.time.DateTime effectiveEndDate = endDate;
if (dayOfWeekEndDateNumber == 6 || dayOfWeekEndDateNumber == 7) {
effectiveEndDate = endDate.minusDays(Math.abs(5 - dayOfWeekEndDateNumber));
}
// How many days have passed counting weekends
int days;
if(ignoreTimeOfDay) {
days = org.joda.time.Days.daysBetween(startDate.toLocalDate(), effectiveEndDate.toLocalDate()).getDays();
} else {
days = org.joda.time.Days.daysBetween(startDate, effectiveEndDate).getDays();
}
// How many weeks have passed
int weeks = days / 7;
// Excess days left. E.g. one week and three days the excess will be 3
int excess = days % 7;
// Excess of days spent for the weekend , then it must be removed two days
// the final number of days
if (excess + dayOfWeekStartDateNumber >= 6) {
// Week count * 5 working days + excess days - the weekend that excess crossed
return weeks * 5 + excess - 2;
}
// Weeks count * 5 working days + excess days
return weeks * 5 + excess;
}
In the earlier version - following snippet was subtracting an extra day. Subtracting -2 no matter if endDate was a Saturday or Sunday.
if (excess + dayOfWeekStartDateNumber >= 6) {
// Week count * 5 working days + excess days - the weekend that excess crossed
return weeks * 5 + excess - 2;
}
Hope that helps!
To improve upon what #samir-machado-de-oliveira posted, here is a function that will calculate days sans weekends without using a loop. I have not benchmarked this against the loop version, but it appears as though it would be faster:
/**
* Gets number of days between two dates. Ignoring weekends.
* #param startDate
* #param endDate
* #return
*/
public static int getDaysBetweenIgnoreWeekends(DateTime startDate, DateTime endDate) {
// If the start date is equal to the closing date, spent 0 days
if (startDate.equals(endDate))
return 0;
// A number that represents the day for the start date, Monday = 1 , Tuesday = 2 , Wednesday = 3 ...
int dayOfWeekStartDateNumber = startDate.getDayOfWeek();
// If the starting date is Saturday or Sunday , pretend to be Monday
if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
int DaysToAdd = 8 - dayOfWeekStartDateNumber;
startDate = startDate.plusDays(DaysToAdd);
dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek().getAsString());
}
// How many days have passed counting weekends
int days = Days.daysBetween(startDate, endDate).getDays();
// How many weeks have passed
int weeks = days / 7;
// Excess days left. E.g. one week and three days the excess will be 3
int excess = days % 7;
// Excess of days spent for the weekend , then it must be removed two days
// the final number of days
if (excess + dayOfWeekStartDateNumber >= 6) {
// Week count * 5 working days + excess days - the weekend that excess crossed
return weeks * 5 + excess - 2;
}
// Weeks count * 5 working days + excess days
return weeks * 5 + excess;
}
Also, here is a version that will allow you to ignore the time of the day, so that if the start date is at 11AM on the start time and the end time is the next day at 10AM it will show as 1 day instead of 0 days.
/**
* Gets number of days between two dates. Ignoring weekends. Ignores Hours.
* #param startDate
* #param endDate
* #return
*/
public static int getDaysBetweenIgnoreWeekends(DateTime startDate, DateTime endDate) {
return getDaysBetweenIgnoreWeekends(startDate,endDate,true);
}
/**
* Gets number of days between two dates. Ignoring weekends.
* #param startDate
* #param endDate
* #param ignoreTimeOfDay
* #return
*/
public static int getDaysBetweenIgnoreWeekends(DateTime startDate, DateTime endDate, boolean ignoreTimeOfDay) {
// If the start date is equal to the closing date, spent 0 days
if (startDate.equals(endDate))
return 0;
if (ignoreTimeOfDay && startDate.toLocalDate().equals(endDate.toLocalDate()))
return 0;
// A number that represents the day for the start date, Monday = 1 , Tuesday = 2 , Wednesday = 3 ...
int dayOfWeekStartDateNumber = startDate.getDayOfWeek();
// If the starting date is Saturday or Sunday , pretend to be Monday
if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
int DaysToAdd = 8 - dayOfWeekStartDateNumber;
startDate = startDate.plusDays(DaysToAdd);
dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek().getAsString());
}
// How many days have passed counting weekends
int days;
if(ignoreTimeOfDay) {
days = Days.daysBetween(startDate.toLocalDate(), endDate.toLocalDate()).getDays();
} else {
days = Days.daysBetween(startDate, endDate).getDays();
}
// How many weeks have passed
int weeks = days / 7;
// Excess days left. E.g. one week and three days the excess will be 3
int excess = days % 7;
// Excess of days spent for the weekend , then it must be removed two days
// the final number of days
if (excess + dayOfWeekStartDateNumber >= 6) {
// Week count * 5 working days + excess days - the weekend that excess crossed
return weeks * 5 + excess - 2;
}
// Weeks count * 5 working days + excess days
return weeks * 5 + excess;
}
Neatly using Java 8 Streams:
public LocalDate[] filterWeekdaysForRange(final LocalDate start,final LocalDate end) {
return Stream.iterate(start, date -> date.plusDays(1))
.limit(ChronoUnit.DAYS.between(start, end)+1)
.filter(d->d.getDayOfWeek() != SATURDAY)
.filter(d->d.getDayOfWeek() != SUNDAY)
.toArray(LocalDate[]::new);
}
This is an adaption of a solution provided here: https://stackoverflow.com/a/38220748/744133
You can use the gregorian calendar to retrieve the day for a particular date. If the string is Saturday or Sunday you can neglect it.
This will return the end date by excluding weekends
public static Date addDaysBySkipWeekend(Date startDate, int numDays) {
Calendar dateCal = Calendar.getInstance();
dateCal.setTime(startDate);
for (int i = 0; i < numDays-1; i++) {
dateCal.add(dateCal.DATE, 1);
if(dateCal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY
|| dateCal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY ){
dateCal.add(dateCal.DATE, 1);
i--;
}
}
return dateCal.getTime();
}

Categories

Resources