如何获取两个 java.util.Date 之间的工作日数,即不包括周末和节假日?假期,我的意思是legally recognized holidays .这一定取决于国家/地区,因为每个国家/地区的假期都不同。
例如,2012-08-27 - 2012-08-24 应该返回 1 而不是 3,因为中间有周末.
我已经看过 Jollyday和 ObjectLab-Kit ,但我不能让他们满足我的需要。我的意思是,它们都有很多有趣的方法,但找不到像 getBusinessDaysCount(Date d1, Date d2)...
最佳答案
最后是一个基于Calendar API 的解决方案:
/**
* Handles holidays by country.
*/
public enum Holidays {
/**
* See <a href="http://www.wikiwand.com/en/Public_holidays_in_France">http://www.wikiwand.com/en/Public_holidays_in_France</a>.
*/
FRANCE {
@Override
protected void addFixedHolidays(Set<Holiday> holidays) {
holidays.add(new Holiday(Calendar.JANUARY, 1));
holidays.add(new Holiday(Calendar.MAY, 1));
holidays.add(new Holiday(Calendar.MAY, 8));
holidays.add(new Holiday(Calendar.JULY, 14));
holidays.add(new Holiday(Calendar.AUGUST, 15));
holidays.add(new Holiday(Calendar.NOVEMBER, 1));
holidays.add(new Holiday(Calendar.NOVEMBER, 11));
holidays.add(new Holiday(Calendar.DECEMBER, 25));
}
@Override
protected void addVariableHolidays(int year, Set<Holiday> holidays) {
Date easterSunday = getEasterSunday(year);
holidays.add(new Holiday(getEasterMonday(easterSunday)));
holidays.add(new Holiday(getAscensionThursday(easterSunday)));
holidays.add(new Holiday(getPentecostMonday(easterSunday)));
}
},
/**
* See <a href="http://www.wikiwand.com/en/Public_holidays_in_the_United_Kingdom">http://www.wikiwand.com/en/Public_holidays_in_the_United_Kingdom</a>.
*/
ENGLAND {
@Override
protected void addFixedHolidays(Set<Holiday> holidays) {
holidays.add(new Holiday(Calendar.JANUARY, 1));
holidays.add(new Holiday(Calendar.DECEMBER, 25));
holidays.add(new Holiday(Calendar.DECEMBER, 26));
}
@Override
protected void addVariableHolidays(int year, Set<Holiday> holidays) {
Date easterSunday = getEasterSunday(year);
holidays.add(new Holiday(getGoodFriday(easterSunday)));
holidays.add(new Holiday(getEasterMonday(easterSunday)));
holidays.add(new Holiday(get(WeekdayIndex.FIRST, Calendar.MONDAY, Calendar.MAY, year)));
holidays.add(new Holiday(get(WeekdayIndex.LAST, Calendar.MONDAY, Calendar.MAY, year)));
holidays.add(new Holiday(get(WeekdayIndex.LAST, Calendar.MONDAY, Calendar.AUGUST, year)));
Holiday christmasDay = new Holiday(Calendar.DECEMBER, 25);
if (christmasDay.isWeekend(year)) {
holidays.add(new Holiday(Calendar.DECEMBER, 27));
}
Holiday boxingDay = new Holiday(Calendar.DECEMBER, 26);
if (boxingDay.isWeekend(year)) {
holidays.add(new Holiday(Calendar.DECEMBER, 28));
}
}
};
public class HolidayException extends Exception {
private static final long serialVersionUID = 1L;
private HolidayException(String message) {
super(message);
}
}
/**
* A holiday is defined by a {@link Calendar#MONTH} and a {@link Calendar#DAY_OF_MONTH}.
*/
private class Holiday {
private final int day;
private final int month;
public Holiday(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
month = calendar.get(Calendar.MONTH);
day = calendar.get(Calendar.DAY_OF_MONTH);
}
public Holiday(int month, int day) {
this.month = month;
this.day = day;
}
public Date toDate(int year) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, month, day);
return calendar.getTime();
}
public boolean isWeekend(int year) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(toDate(year));
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
return dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof Holiday)) {
return false;
} else {
Holiday holiday = (Holiday) obj;
return holiday.month == month && holiday.day == day;
}
}
@Override
public int hashCode() {
return Arrays.hashCode(new int[] { month, day });
}
}
/**
* Use with {@link Holidays#get(WeekdayIndex, int, int, int)}.<br />
* <br />
* Example: <code>Holidays.get(WeekdayIndex.FIRST, Calendar.MONDAY, Calendar.MAY, 2000)</code>.
*/
public enum WeekdayIndex {
FIRST(1), SECOND(2), THIRD(3), FOURTH(4), LAST(null);
private final Integer index;
private WeekdayIndex(Integer index) {
this.index = index;
}
private boolean is(int count) {
return index != null && index == count;
}
}
private final Set<Holiday> fixedHolidays = new HashSet<Holiday>();
private final Map<Integer, Set<Holiday>> variableHolidays = new HashMap<Integer, Set<Holiday>>();
private Holidays() {
addFixedHolidays(fixedHolidays);
}
protected abstract void addFixedHolidays(Set<Holiday> holidays);
protected abstract void addVariableHolidays(int year, Set<Holiday> holidays);
/**
* Returns the number of business days between two dates.
*
* @param d1
* The first date.
* @param d2
* The second date.
* @return The number of business days between the two provided dates.
* @throws HolidayException
* If <code>d1</code> or <code>d2</code> is not a business day.
*/
public int getBusinessDayCount(Date d1, Date d2) throws HolidayException {
Calendar calendar = Calendar.getInstance();
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
try {
d1 = formatter.parse(formatter.format(d1));
d2 = formatter.parse(formatter.format(d2));
} catch (ParseException ignore) {
// cannot happen
}
if (!isBusinessDay(d1) || !isBusinessDay(d2)) {
throw new HolidayException("Input dates must be business days");
}
int businessDayCount = 0;
Date min = d1.before(d2) ? d1 : d2;
Date max = min.equals(d2) ? d1 : d2;
calendar.setTime(min);
while (calendar.getTime().before(max)) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
if (isBusinessDay(calendar.getTime())) {
businessDayCount++;
}
}
return businessDayCount;
}
/**
* Returns whether a date is a business day.
*
* @param date
* The date.
* @return <code>true</code> if the <code>date</code> is a business day, <code>false</code> otherwise.
*/
public boolean isBusinessDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY) {
return false;
} else if (isFixedHoliday(date)) {
return false;
} else if (isVariableHoliday(date)) {
return false;
}
return true;
}
private boolean isFixedHoliday(Date date) {
return fixedHolidays.contains(new Holiday(date));
}
private boolean isVariableHoliday(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
Set<Holiday> yearHolidays;
if (!variableHolidays.containsKey(year)) {
// variable holidays have not been calculated for this year yet
yearHolidays = new HashSet<Holiday>();
addVariableHolidays(year, yearHolidays);
variableHolidays.put(year, yearHolidays);
} else {
yearHolidays = variableHolidays.get(year);
}
return yearHolidays.contains(new Holiday(date));
}
public static Date getEasterSunday(int year) {
// credits: https://www.wikiwand.com/en/Computus#/Anonymous_Gregorian_algorithm
Calendar calendar = Calendar.getInstance();
int initialYear = year;
if (year < 1900) {
year += 1900;
}
int a = year % 19;
int b = year / 100;
int c = year % 100;
int d = b / 4;
int e = b % 4;
int f = (b + 8) / 25;
int g = (b - f + 1) / 3;
int h = (19 * a + b - d - g + 15) % 30;
int i = c / 4;
int j = c % 4;
int k = (32 + 2 * e + 2 * i - h - j) % 7;
int l = (a + 11 * h + 22 * k) / 451;
int m = (h + k - 7 * l + 114) % 31;
int month = (h + k - 7 * l + 114) / 31 - 1;
int day = m + 1;
calendar.set(initialYear, month, day);
return calendar.getTime();
}
public static Date getGoodFriday(Date easterSunday) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(easterSunday);
calendar.add(Calendar.DAY_OF_MONTH, -2);
return calendar.getTime();
}
public static Date getEasterMonday(Date easterSunday) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(easterSunday);
calendar.add(Calendar.DAY_OF_MONTH, 1);
return calendar.getTime();
}
public static Date getAscensionThursday(Date easterSunday) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(easterSunday);
calendar.add(Calendar.DAY_OF_MONTH, 39);
return calendar.getTime();
}
public static Date getPentecostMonday(Date easterSunday) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(easterSunday);
calendar.add(Calendar.DAY_OF_MONTH, 50);
return calendar.getTime();
}
public static Date get(WeekdayIndex weekdayIndex, int dayOfWeek, int month, int year) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, month, 1);
int count = 0;
Date last = null;
do {
if (calendar.get(Calendar.DAY_OF_WEEK) == dayOfWeek) {
count++;
last = calendar.getTime();
if (weekdayIndex.is(count)) {
return last;
}
}
calendar.add(Calendar.DAY_OF_MONTH, 1);
} while (calendar.get(Calendar.MONTH) == month);
if (weekdayIndex.equals(WeekdayIndex.LAST)) {
return last;
}
return null;
}
}
调用方式:
Holidays.FRANCE.getBusinessDayCount(d1, d2);
关于java - 两个日期之间的差异,仅包括工作日(即不包括周末和节假日),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12143194/
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build
我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行