任何人都可以向我指出一些Java片段,其中我可以在两个日期之间获得业务(周六和周日除外)。
答案 0 :(得分:47)
解决方案无循环:
static long days(Date start, Date end){
//Ignore argument check
Calendar c1 = Calendar.getInstance();
c1.setTime(start);
int w1 = c1.get(Calendar.DAY_OF_WEEK);
c1.add(Calendar.DAY_OF_WEEK, -w1);
Calendar c2 = Calendar.getInstance();
c2.setTime(end);
int w2 = c2.get(Calendar.DAY_OF_WEEK);
c2.add(Calendar.DAY_OF_WEEK, -w2);
//end Saturday to start Saturday
long days = (c2.getTimeInMillis()-c1.getTimeInMillis())/(1000*60*60*24);
long daysWithoutWeekendDays = days-(days*2/7);
// Adjust days to add on (w2) and days to subtract (w1) so that Saturday
// and Sunday are not included
if (w1 == Calendar.SUNDAY && w2 != Calendar.SATURDAY) {
w1 = Calendar.MONDAY;
} else if (w1 == Calendar.SATURDAY && w2 != Calendar.SUNDAY) {
w1 = Calendar.FRIDAY;
}
if (w2 == Calendar.SUNDAY) {
w2 = Calendar.MONDAY;
} else if (w2 == Calendar.SATURDAY) {
w2 = Calendar.FRIDAY;
}
return daysWithoutWeekendDays-w1+w2;
}
答案 1 :(得分:42)
public static int getWorkingDaysBetweenTwoDates(Date startDate, Date endDate) {
Calendar startCal = Calendar.getInstance();
startCal.setTime(startDate);
Calendar endCal = Calendar.getInstance();
endCal.setTime(endDate);
int workDays = 0;
//Return 0 if start and end are the same
if (startCal.getTimeInMillis() == endCal.getTimeInMillis()) {
return 0;
}
if (startCal.getTimeInMillis() > endCal.getTimeInMillis()) {
startCal.setTime(endDate);
endCal.setTime(startDate);
}
do {
//excluding start date
startCal.add(Calendar.DAY_OF_MONTH, 1);
if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
++workDays;
}
} while (startCal.getTimeInMillis() < endCal.getTimeInMillis()); //excluding end date
return workDays;
}
开始日期和结束日期是独家的,只有给定的日期 日期将被计算在内。不包括开始日期和结束日期。
答案 2 :(得分:12)
天数与ChronoUnit.DAYS.between(start, end)
的定义方式相同,这意味着星期一到星期五之间有4
天。由于我们只对工作日感兴趣,因此我们必须减去周末,因此从周五到周二将有2
个工作日(仅计算endDay - startDay
并减去周末的2
)。如果您想要包含结果,请在结果中添加1
,即不是天数。
我提出两种解决方案。
第一种解决方案(5线,短而神秘):
import java.time.*;
import java.time.temporal.*;
public static long calcWeekDays1(final LocalDate start, final LocalDate end) {
final DayOfWeek startW = start.getDayOfWeek();
final DayOfWeek endW = end.getDayOfWeek();
final long days = ChronoUnit.DAYS.between(start, end);
final long daysWithoutWeekends = days - 2 * ((days + startW.getValue())/7);
//adjust for starting and ending on a Sunday:
return daysWithoutWeekends + (startW == DayOfWeek.SUNDAY ? 1 : 0) + (endW == DayOfWeek.SUNDAY ? 1 : 0);
}
第二个解决方案:
public static long calcWeekDays2(final LocalDate start, final LocalDate end) {
final int startW = start.getDayOfWeek().getValue();
final int endW = end.getDayOfWeek().getValue();
final long days = ChronoUnit.DAYS.between(start, end);
long result = days - 2*(days/7); //remove weekends
if (days % 7 != 0) { //deal with the rest days
if (startW == 7) {
result -= 1;
} else if (endW == 7) { //they can't both be Sunday, otherwise rest would be zero
result -= 1;
} else if (endW < startW) { //another weekend is included
result -= 2;
}
}
return result;
}
答案 3 :(得分:10)
我使用了盛源路的解决方案,但我需要修正一个方法被调用的情况,其中一个日期是在星期六而另一个是星期日 - 否则答案是关闭一天:
static long days(Date start, Date end){
//Ignore argument check
Calendar c1 = GregorianCalendar.getInstance();
c1.setTime(start);
int w1 = c1.get(Calendar.DAY_OF_WEEK);
c1.add(Calendar.DAY_OF_WEEK, -w1 + 1);
Calendar c2 = GregorianCalendar.getInstance();
c2.setTime(end);
int w2 = c2.get(Calendar.DAY_OF_WEEK);
c2.add(Calendar.DAY_OF_WEEK, -w2 + 1);
//end Saturday to start Saturday
long days = (c2.getTimeInMillis()-c1.getTimeInMillis())/(1000*60*60*24);
long daysWithoutSunday = days-(days*2/7);
if (w1 == Calendar.SUNDAY) {
w1 = Calendar.MONDAY;
}
if (w2 == Calendar.SUNDAY) {
w2 = Calendar.MONDAY;
}
return daysWithoutSunday-w1+w2;
}
答案 4 :(得分:5)
现代方法是使用java.time类。
LocalDate
LocalDate
类表示没有时间且没有时区的仅限日期的值。
LocalDate start = LocalDate.of( 2016 , 1 , 23 );
LocalDate stop = start.plusMonths( 1 );
DayOfWeek
枚举 DayOfWeek
enum为一周中的每个服务器日提供singleton个实例。
DayOfWeek dow = start.getDayOfWeek();
if( dow.equals( DayOfWeek.SATURDAY ) || dow.equals( DayOfWeek.SUNDAY ) ) …
我们可以收集所需日期为List
。
int initialCapacity = Duration.between( start , stop ).toDays() ;
List<LocalDate> dates = new ArrayList<>( initialCapacity );
…
if( dow.equals( DayOfWeek.SATURDAY ) || dow.equals( DayOfWeek.SUNDAY ) ) {
dates.add( date );
…
EnumSet
是一种非常高效,快速且内存不足的Set
实现。我们可以使用EnumSet
代替上面提到的if
语句。
Set<DayOfWeek> weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY ) ;
…
if( weekend.contains( dayOfWeek ) ) …
把它们放在一起。
LocalDate date = start ;
while( date.isBefore( stop ) ) {
if( ! weekend.contains( date.getDayOfWeek() ) ) { // If not weekend, collect this LocalDate.
dates.add( date ) ;
}
// Prepare for next loop.
date = date.plusDays( 1 ); // Increment to next day.
}
nextWorkingDay
TemporalAdjuster 另一种方法是使用ThreeTen-Extra项目添加适用于java.time的类。
Temporals
类添加了TemporalAdjuster
的其他实现来操作日期时间值。我们希望nextWorkingDay
调整器在跳过星期六和星期六时增加日期。周日。
LocalDate start = LocalDate.of( 2016 , 1 , 23 );
LocalDate stop = start.plusMonths( 1 );
int initialCapacity = Duration.between( start , stop ).toDays() ;
List<LocalDate> dates = new ArrayList<>( initialCapacity );
LocalDate date = start.minusDays( 1 ); // Start a day ahead.
while( date.isBefore( stop ) ) {
date = date.with( org.threeten.extra.Temporals.nextWorkingDay() );
// Double-check ending date as the `nextWorkingDay` adjuster could move us past the stop date.
if( date.isBefore( stop ) ) {
dates.add( date ) ;
}
}
我对本页各种答案中各种方法的表现感到好奇。我只考虑现代的 java.time 代码,而不是使用麻烦的遗留Date
/ Calendar
类的代码。
以下是四种方法,每种方法都会返回经过的天数。
一个人使用Answer by Roland中看到的基于数学的聪明方法。
private long countWeekDaysMath ( LocalDate start , LocalDate stop ) {
// Code taken from Answer by Roland.
// https://stackoverflow.com/a/44942039/642706
long count = 0;
final DayOfWeek startW = start.getDayOfWeek();
final DayOfWeek stopW = stop.getDayOfWeek();
final long days = ChronoUnit.DAYS.between( start , stop );
final long daysWithoutWeekends = days - 2 * ( ( days + startW.getValue() ) / 7 );
//adjust for starting and ending on a Sunday:
count = daysWithoutWeekends + ( startW == DayOfWeek.SUNDAY ? 1 : 0 ) + ( stopW == DayOfWeek.SUNDAY ? 1 : 0 );
return count;
}
本答案中的两种使用方法:(a)访问每个日期,在传统循环中逐个递增。
private long countWeekDaysVisit ( LocalDate start , LocalDate stop ) {
// Code taken from Answer by Basil Bourque.
// https://stackoverflow.com/a/40369140/642706
long count = 0;
Set < DayOfWeek > weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY );
LocalDate ld = start;
while ( ld.isBefore( stop ) ) {
if ( ! weekend.contains( ld.getDayOfWeek() ) ) { // If not weekend, collect this LocalDate.
count++;
}
// Prepare for next loop.
ld = ld.plusDays( 1 ); // Increment to next day.
}
return count;
}
......和,(b)使用TemporalAdjuster
实施org.threeten.extra.Temporals.nextWorkingDay()
。
private long countWeekDaysAdjuster ( LocalDate start , LocalDate stop ) {
// Code taken from Answer by Basil Bourque.
// https://stackoverflow.com/a/40369140/642706
long count = 0;
Set < DayOfWeek > weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY );
TemporalAdjuster nextWorkingDayTA = org.threeten.extra.Temporals.nextWorkingDay();
LocalDate ld = start;
if ( weekend.contains( ld.getDayOfWeek() ) ) {
ld = ld.with( nextWorkingDayTA );
}
while ( ld.isBefore( stop ) ) {
count++;
// Prepare for next loop.
ld = ld.with( nextWorkingDayTA ); // Increment to next working day (non-weekend day).
}
return count;
}
最后一个使用了Answer by Ravindra Ranwala中的Java Streams方法。
private long countWeekDaysStream ( LocalDate start , LocalDate stop ) {
// Code taken from the Answer by Ravindra Ranwala.
// https://stackoverflow.com/a/51010738/642706
long count = 0;
Set < DayOfWeek > weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY );
final long weekDaysBetween = start.datesUntil( stop )
.filter( d -> ! weekend.contains( d.getDayOfWeek() ) )
.count();
return count;
}
测试安全带。
警告:
TemporalAdjuster
可以在我们的方法之外缓存。测试工具。
LocalDate start = LocalDate.of( 2018 , Month.JANUARY , 1 );
LocalDate stop = start.plusYears( 1 );
int runs = 100_000;
long go = System.nanoTime();
for ( int i = 1 ; i <= runs ; i++ ) {
long count = this.countWeekDaysMath( start , stop );
}
long elapsedMath = ( System.nanoTime() - go );
go = System.nanoTime();
for ( int i = 1 ; i <= runs ; i++ ) {
long count = this.countWeekDaysVisit( start , stop );
}
long elapsedVisit = ( System.nanoTime() - go );
go = System.nanoTime();
for ( int i = 1 ; i <= runs ; i++ ) {
long count = this.countWeekDaysStream( start , stop );
}
long elapsedAdjuster = ( System.nanoTime() - go );
go = System.nanoTime();
for ( int i = 1 ; i <= runs ; i++ ) {
long count = this.countWeekDaysStream( start , stop );
}
long elapsedStream = ( System.nanoTime() - go );
System.out.println( "math: " + elapsedMath + " each: " + ( elapsedMath / runs ) );
System.out.println( "visit: " + elapsedVisit + " each: " + ( elapsedVisit / runs ) );
System.out.println( "adjuster: " + elapsedAdjuster + " each: " + ( elapsedAdjuster / runs ) );
System.out.println( "stream: " + elapsedStream + " each: " + ( elapsedStream / runs ) );
使用Oracle JDK 10.0.1和 ThreeTen-Extra 版本1.3.2在我的MacBook Pro(Sierra)上运行时,我得到的结果始终接近以下内容。正如我们所期望的那样,数学解决方案只是其他一小部分,几百纳米,而不是几千纳米。在其他三个中, TemporalAdjuster
是最长的,每个总是超过10,000纳米。访问量和流量均低于10,000纳米,访问量明显快于流量。正如围绕互联网的其他示例所示, Java Streams通常会生成漂亮的短代码,而且通常会运行得更长,在这种情况下会长约20%。
数学:18313309每个:183
访问:708420626每个:7084
理算师:1002157240每人:10021
stream:924724750 each:9247
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 5 :(得分:4)
我没有基于Java的解决方案,但有一个PHP,希望它有所帮助:
function getDate($days) {
for ($i = 0; $i < $days; $i ++) {
if (date('N' , strtotime('+' . ($i + 1) . ' days')) > 5) {
$days++;
}
}
return date('l, F jS', strtotime('+' . $days . ' days', time()));
}
答案 6 :(得分:3)
几乎所有解决方案都已过时且难以理解。但是,这是一个非常简洁易读的解决方案。
此方法使用Java 9及更高版本中内置的Java Stream方法提供的LocalDate::datesUntil
。
you split the **str** into substrings and stored in **res** array,again
your
trying to split the substrings, you should specify that which substring going
to split.
void displayResult() {
String str = "tamilnadu||chennai-karanataka||bengaluru";
String[] res = str.split("\\-");
System.out.println(res.length);
**String[] result = res[0].toString().split("\\|");**
for (String string : result) {
System.out.println(string);
}
System.out.println(result.length);
}
output:
2
tmailnadu
chennai
3
LocalDate startDate = LocalDate.of(2018, 5, 2); LocalDate endDate = LocalDate.now(); Set<DayOfWeek> weekend = EnumSet.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY); final long weekDaysBetween = startDate.datesUntil(endDate) .filter(d -> !weekend.contains(d.getDayOfWeek())) .count();
返回按顺序排列的日期流。的 返回的流从该日期(包括该日期)开始,然后转到 endExclusive(独占)(以1天为增量)。
然后将所有星期六和星期日过滤掉。最后一步是获取剩余工作日的计数。
Java-9已于一年前发布,因为现在对我来说使用它是合理的。
答案 7 :(得分:2)
这是我没有循环的例子。算法与卢声远 Shengyuan Lus一样,但我使用了JodaTime的一些功能。
{{1}}
答案 8 :(得分:2)
Piyush解决方案中的do
while
错误,应该是:
do {
if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
++workDays;
}
startCal.add(Calendar.DAY_OF_MONTH, 1);
} while (startCal.getTimeInMillis() < endCal.getTimeInMillis());
答案 9 :(得分:1)
这是我没有循环的例子。它是此示例中的一个类,因为我在一些JSON输出中对其进行序列化。基本上我计算出两个日期之间的天数,除以7并指定一个长整数值来表示周数。取原始天数并减去周末数* 2。这不是很完美 - 如果有一个“宿醉”,你需要解决这个问题。开始接近一周结束并持续周末。为了纠正这个问题,我会在开始时找到一周中的某一天并找到剩余的天数,然后将它们加在一起以找到“宿醉”。 - 如果超过5则是周末。它并不完美,根本不考虑假期。看见没有Joda。也就是说时区也存在问题。
import java.io.Serializable;
import java.util.Date;
public class BusinessDayCalculator implements Serializable {
private static long DAY = 86400000l;
private Date startTime;
private Date endTime;
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getStartTime() {
return startTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public Date getEndTime() {
return endTime;
}
public long getHours() {
return (this.endTime.getTime() - this.startTime.getTime())/(1000*60*60);
}
public long getBusinessDays(){
long startDay = getDayFromDate(this.startTime);
long endDay = getDayFromDate(this.endTime);
long totalDays = endDay-startDay;
long totalWeekends = totalDays/7;
long day = getDay(this.startTime);
long hangover = totalDays % 7;
long intoWeekend = day + hangover;
if(intoWeekend>5){
totalWeekends++;
}
long totalBusinessDays = totalDays - (totalWeekends *2);
/*
System.out.println("Days = " + day );
System.out.println("Hangover = " + hangover );
System.out.println("Total Days = " + totalDays);
System.out.println("Total Weekends = " + totalWeekends);
System.out.println("Total Business Days = " + totalBusinessDays);
*/
return totalBusinessDays;
}
private long getDayFromDate( Date date ){
long d = date.getTime() / DAY;
return d;
}
private long getDay( Date date ){
long daysSinceEpoc = getDayFromDate(date);
long day = daysSinceEpoc % 7;
day = day + 4;
if(day>6) day = day - 7;
return day;
}
}
答案 10 :(得分:1)
startCal.add
应该添加到Calendar.DATE
字段,而不是Calendar.DAY_OF_MONTH
,我在12月/ 1月期间得到了奇怪的结果。
答案 11 :(得分:1)
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/**
*
* @author varun.vishwakarma
*
*/
public class FindWeekendsInDateRange {
static HashMap<Integer, String> daysOfWeek=null;
static {
daysOfWeek = new HashMap<Integer, String>();
daysOfWeek.put(new Integer(1), "Sun");
daysOfWeek.put(new Integer(2), "Mon");
daysOfWeek.put(new Integer(3), "Tue");
daysOfWeek.put(new Integer(4), "Wed");
daysOfWeek.put(new Integer(5), "Thu");
daysOfWeek.put(new Integer(6), "Fri");
daysOfWeek.put(new Integer(7), "Sat");
}
/**
*
* @param from_date
* @param to_date
* @return
*/
public static List<Date> calculateWeekendsInDateReange(Date fromDate, Date toDate) {
List<Date> listOfWeekends = new ArrayList<Date>();
Calendar from = Calendar.getInstance();
Calendar to = Calendar.getInstance();
from.setTime(fromDate);
to.setTime(toDate);
while (from.getTimeInMillis() < to.getTimeInMillis()) {
if (daysOfWeek.get(from.get(Calendar.DAY_OF_WEEK)) == "Sat") {
Date sat = from.getTime();
listOfWeekends.add(sat);
} else if (daysOfWeek.get(from.get(Calendar.DAY_OF_WEEK)) == "Sun") {
Date sun = from.getTime();
listOfWeekends.add(sun);
}
from.add(Calendar.DAY_OF_MONTH, 1);
}
return listOfWeekends;
}
public static void main(String[] args) {
String fromDate = "7-Oct-2019";
String toDate = "25-Oct-2019";
System.out.println(FindWeekendsInDateRange.calculateWeekendsInDateReange(new Date(fromDate), new Date(toDate)));
}
}
答案 12 :(得分:0)
该计划考虑循环方法,但考虑下班后工作时间到下一个工作日办公时间开始的活动
公共类BusinessDayCalculator {
private final String DATE_FORMAT = "dd/MM/yyyy HH:mm:ss";
private final int OFFICE_START_HOUR = 9;
private final int OFFICE_CLOSE_HOUR = 17;
private final int TOTAL_MINS_IN_BUSINESS_DAY = (OFFICE_CLOSE_HOUR - OFFICE_START_HOUR)*60;
public void dateDifference(String start, String end){
Date startDate = validateStringToDate(start);
Date endDate = validateStringToDate(end);
System.out.println(startDate);
System.out.println(endDate);
Calendar startDay = convertDateToCalendar(startDate);
Calendar tempDay = (Calendar) startDay.clone();
Calendar endDay = convertDateToCalendar(endDate);
System.out.println(startDay.getTime());
System.out.println(endDay.getTime());
int workDays = -1;
int startDayDifference = 0;
int endDayDifference = 0;
int hours = 0;
int minsRemainder = 0;
if(!(startDay.get(Calendar.DAY_OF_YEAR) == endDay.get(Calendar.DAY_OF_YEAR)
&& startDay.get(Calendar.YEAR) == endDay.get(Calendar.YEAR))){
do{
tempDay.add(Calendar.DAY_OF_MONTH, 1);
if(tempDay.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY
&& tempDay.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY){
workDays++;
}
}while(tempDay.getTimeInMillis() <= endDay.getTimeInMillis());
if(workDays > 0){
workDays = workDays - 1;
}
}
startDayDifference = hourDifferenceInMinutesOfStartDay(startDay);
endDayDifference = hourDifferenceInMinutesOfEndDay(endDay);
minsRemainder = (startDayDifference + endDayDifference) % TOTAL_MINS_IN_BUSINESS_DAY;
workDays = workDays + ((startDayDifference + endDayDifference) / TOTAL_MINS_IN_BUSINESS_DAY);
hours = minsRemainder/60;
minsRemainder = minsRemainder % 60;
System.out.println(workDays + "d "+ hours + "hrs " + minsRemainder + " mins");
}
private int hourDifferenceInMinutesOfEndDay(Calendar endDay) {
long endTimestamp = endDay.getTimeInMillis();
System.out.println(endTimestamp);
endDay.set(Calendar.HOUR_OF_DAY, OFFICE_START_HOUR);
endDay.set(Calendar.MINUTE,0);
long endDayOfficeStartTimestamp = endDay.getTimeInMillis();
System.out.println(endDayOfficeStartTimestamp);
int difference = (int)((endTimestamp - endDayOfficeStartTimestamp) / 1000) / 60;
System.out.println(difference);
return difference;
}
private int hourDifferenceInMinutesOfStartDay(Calendar startDay) {
long starttimestamp = startDay.getTimeInMillis();
System.out.println(starttimestamp);
startDay.set(Calendar.HOUR_OF_DAY, OFFICE_CLOSE_HOUR);
startDay.set(Calendar.MINUTE,0);
long startDayOfficeCloseTimestamp = startDay.getTimeInMillis();
System.out.println(startDayOfficeCloseTimestamp);
int difference = (int)((startDayOfficeCloseTimestamp - starttimestamp) / 1000) / 60;
System.out.println(difference);
return difference;
}
public Calendar convertDateToCalendar(Date date){
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
if(calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY
|| calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY){
calendar = handleActivityOnAfterWorkHoursOrWeekendOrHolidays(calendar);
}
if(calendar.get(Calendar.HOUR_OF_DAY) >= OFFICE_CLOSE_HOUR
&& calendar.get(Calendar.MINUTE) > 0){
calendar = handleActivityOnAfterWorkHoursOrWeekendOrHolidays(calendar);
}
if(calendar.get(Calendar.HOUR_OF_DAY) < OFFICE_START_HOUR){
calendar.set(Calendar.HOUR_OF_DAY, OFFICE_START_HOUR);
calendar.set(Calendar.MINUTE,0);
}
return calendar;
}
private Calendar handleActivityOnAfterWorkHoursOrWeekendOrHolidays(Calendar calendar) {
do{
calendar.add(Calendar.DAY_OF_MONTH, 1);
}while(isHoliday(calendar));
calendar.set(Calendar.HOUR_OF_DAY, OFFICE_START_HOUR);
calendar.set(Calendar.MINUTE,0);
return calendar;
}
private boolean isHoliday(Calendar calendar) {
if(calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY
|| calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY){
return true;
}
return false;
}
public Date validateStringToDate(String input){
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
Date date = null;
try{
date = dateFormat.parse(input);
}catch(ParseException exception){
System.out.println("invalid date format");
throw new RuntimeException("invalid date format");
}
return date;
}
public static void main(String[] args){
BusinessDayCalculator calc = new BusinessDayCalculator();
String startDate = "27/12/2016 11:38:00";
String endDate = "04/01/2017 12:38:00";
calc.dateDifference(startDate, endDate);
}
}
答案 13 :(得分:0)
这里是使用公式(wd2 - wd1 + 7)%7的任何工作日子集的解决方案,用于计算由数字1-7表示的任意两个工作日(wd1,wd2)之间的距离。
public long countOccurrences(LocalDate startDate, LocalDate endDate, Set<DayOfWeek> daysOfWeek) {
long periodLength = ChronoUnit.DAYS.between(startDate, endDate) + 1;
long fullWeeks = periodLength / 7;
long residualWeekLength = periodLength % 7;
return fullWeeks * daysOfWeek.size()
+ daysOfWeek.stream().mapToLong(
// Yields either 1 or 0, depending on whether the residual week contains the target day or not.
weekday ->
residualWeekLength > (weekday.getValue() - startDate.getDayOfWeek().getValue() + 7) % 7 ? 1 : 0
).sum();
}
对于原始问题(周一至周五),它被称为例如用:
countOccurrences(LocalDate.of(2016, 2, 8), LocalDate.of(2016, 2, 26), new HashSet(Arrays.asList(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY, DayOfWeek.FRIDAY)))
答案 14 :(得分:0)
在groovy中:
public static int getWorkingDaysBetweenDates (Date start, Date end) {
def totalDays = (Integer) (end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24)
def int workingDays = 0
(0..totalDays).each { def dow = (start + it)[Calendar.DAY_OF_WEEK]; if(dow != Calendar.SATURDAY && dow != Calendar.SUNDAY){workingDays++} }
workingDays
}
答案 15 :(得分:0)
使用java 8
可以轻松完成,示例功能:
long getBusinessDaysDifference(LocalDate startDate, LocalDate endDate) {
EnumSet<DayOfWeek> weekend = EnumSet.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY);
List<LocalDate> list = Lists.newArrayList();
LocalDate start = startDate;
while (start.isBefore(endDate)) {
list.add(start);
start = start.plus(1, ChronoUnit.DAYS);
}
long numberOfDays = list.stream().filter(d -> !weekend.contains(d.getDayOfWeek())).count();
return numberOfDays;
}
说明:
off-days
中定义您的EnumSet
(在这种情况下为周末)。EnumSet
中删除一天中发生的任何事情来减少结果列表。注意:此功能可以优化,但作为起点可能会有所帮助。
答案 16 :(得分:0)
这个线程充满了失败的解决方案...我首先编写了一个满足我的需求的测试文件,然后发现Roland的两个解决方案都失败了,Amir也失败了。我想要一个使用Java 8且不使用循环的解决方案,因为我必须说为什么?
这是测试文件:
@Test
public void test() {
LocalDate d1 = LocalDate.of(2018, 8, 1);
LocalDate d2 = LocalDate.of(2018, 8, 2);
LocalDate d3 = LocalDate.of(2018, 8, 3);
LocalDate d4 = LocalDate.of(2018, 8, 4);
LocalDate d5 = LocalDate.of(2018, 8, 5);
LocalDate d6 = LocalDate.of(2018, 8, 6);
LocalDate d7 = LocalDate.of(2018, 8, 7);
LocalDate d8 = LocalDate.of(2018, 8, 8);
LocalDate d9 = LocalDate.of(2018, 8, 9);
LocalDate d10 = LocalDate.of(2018, 8, 10);
LocalDate d15 = LocalDate.of(2018, 8, 15);
LocalDate dsep = LocalDate.of(2018, 9, 5);
// same day : 0 days between
Assert.assertEquals(0, DateUtils.calcWeekDays1(d1, d1));
Assert.assertEquals(1, DateUtils.calcWeekDays1(d1, d2));
Assert.assertEquals(2, DateUtils.calcWeekDays1(d1, d3));
// end on week-end
Assert.assertEquals(2, DateUtils.calcWeekDays1(d1, d4));
Assert.assertEquals(2, DateUtils.calcWeekDays1(d1, d5));
// next week
Assert.assertEquals(3, DateUtils.calcWeekDays1(d1, d6));
Assert.assertEquals(4, DateUtils.calcWeekDays1(d1, d7));
Assert.assertEquals(5, DateUtils.calcWeekDays1(d1, d8));
Assert.assertEquals(6, DateUtils.calcWeekDays1(d1, d9));
Assert.assertEquals(7, DateUtils.calcWeekDays1(d1, d10));
// start on saturday
Assert.assertEquals(0, DateUtils.calcWeekDays1(d4, d5));
Assert.assertEquals(0, DateUtils.calcWeekDays1(d4, d6));
Assert.assertEquals(1, DateUtils.calcWeekDays1(d4, d7));
// start on sunday
Assert.assertEquals(0, DateUtils.calcWeekDays1(d5, d5));
Assert.assertEquals(0, DateUtils.calcWeekDays1(d5, d6));
Assert.assertEquals(1, DateUtils.calcWeekDays1(d5, d7));
// go to next week
Assert.assertEquals(10, DateUtils.calcWeekDays1(d1, d15));
// next month
Assert.assertEquals(25, DateUtils.calcWeekDays1(d1, dsep));
// start sat, go to next month
Assert.assertEquals(22, DateUtils.calcWeekDays1(d4, dsep));
}
这是我建议的解决方案,非常简单。只需让java计算周数,乘以5,然后加上补偿差额所需的天数即可;唯一的技巧是调整开始和结束,以免出现周末:
public static long calcWeekDays1(LocalDate start, LocalDate end) {
if (start.getDayOfWeek().getValue() > 5) {
start = start.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
}
if (end.getDayOfWeek().getValue() > 5) {
end = end.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
}
if (start.isAfter(end)) { // may happen if you start sat. and end sunday
return 0;
}
long weeks = ChronoUnit.WEEKS.between(start, end);
if (start.getDayOfWeek().getValue() > end.getDayOfWeek().getValue()) {
weeks += 1;
}
return 5 * weeks + end.getDayOfWeek().getValue() - start.getDayOfWeek().getValue();
}
现在,如果我的代码也失败了,我会显得很愚蠢:)
答案 17 :(得分:0)
public long getNumberOfWeekDayBetweenDates(LocalDate startDate,LocalDate endDate,String dayOfWeek){ 长结果= -1; 如果(startDate!= null && endDate!= null && dayOfWeek!= null &&(startDate.isBefore(endDate)|| startDate.isEqual(endDate))){ java.time.DayOfWeek namedDayOfWeek = java.time.DayOfWeek.valueOf(dayOfWeek); //在间隔中找到星期的第一天 LocalDate firstOccurrence = startDate.with(TemporalAdjusters.nextOrSame(givenDayOfWeek)); //同样在上周一找到 LocalDate lastOccurrence = endDate.with(TemporalAdjusters.previousOrSame(givenDayOfWeek)); if(firstOccurrence!= null && lastOccurrence!= null){ //计算第一次到最后一次出现之间的周数,然后加上1,因为结束日期是唯一的 结果= ChronoUnit.WEEKS.between(firstOccurrence,lastOccurrence)+ 1; } else if(firstOccurrence == null && lastOccurrence == null){ //没有发生 结果= 0; }其他{ 结果= 1; } } 返回结果; }
答案 18 :(得分:0)
无循环和包含间隔的Java 8解决方案:
public long getDaysWithoutSundays(LocalDate startDate, LocalDate endDate) {
long numberOfDays = ChronoUnit.DAYS.between(startDate, endDate) + 1;
long numberOfSundays = numberOfDays / 7;
long rest = numberOfDays % 7;
if (rest > 0) {
int startToEnd = startDate.getDayOfWeek().getValue() - endDate.getDayOfWeek().getValue();
if (startToEnd > 0) {
numberOfSundays++;
}
else {
if (endDate.getDayOfWeek().equals(DayOfWeek.SUNDAY)) {
numberOfSundays++;
}
}
}
return numberOfDays - numberOfSundays;
}
答案 19 :(得分:0)
对于最新java版本支持的LocalDate
,您可以尝试以下功能。
它提供对函数getDayOfWeek()
的支持。
Java 中 getDayOfWeek()
类的 LocalDate
方法获取星期几字段,它是一个枚举 DayOfWeek。 >
public static int getWeekEndCount(LocalDate fromDate, LocalDate toDate) {
int saturday = 0;
int sunday = 0;
while (!fromDate.isAfter(toDate)) {
if (fromDate.getDayOfWeek().equals(DayOfWeek.SATURDAY))
saturday++;
else if (fromDate.getDayOfWeek().equals(DayOfWeek.SUNDAY))
sunday++;
fromDate = fromDate.plusDays(1);
}
System.out.println("Saturday count=="+saturday);
System.out.println("Sunday count=="+sunday);
return saturday+sunday;
}