求可根据指定日期识别美国节假日名称的Freemarker方法
解决方案
Freemarker本身没有内置的美国节假日判断函数,你需要自定义一个节假日校验函数,再修改原有的getPreviousBusinessDay逻辑,确保返回的日期既不是周末也不在公司认可的节假日列表里。
步骤1:实现节假日判断函数isUSHoliday
先编写一个函数来判断指定日期是否属于你公司认可的10个美国节假日。下面是包含常见美国节假日判断逻辑的示例(你可以根据公司实际规则调整调休或节假日范围):
<#function isUSHoliday date> <#local year = date?date_part("yyyy")?number> <#local month = date?date_part("MM")?number> <#local day = date?date_part("dd")?number> <#local dayOfWeek = date?day_of_week> <!-- 1=周日, 2=周一, ...,7=周六 --> <!-- 1. 新年(1月1日,若周末则调休到周一/周五) --> <#if (month == 1 && day == 1) || (month == 12 && day == 31 && dayOfWeek == 7) || (month == 1 && day == 2 && dayOfWeek == 2)> <#return true> </#if> <!-- 2. 马丁路德金纪念日(1月第三个周一) --> <#if month == 1> <#local firstMonday = 1 + (2 - dayOfWeek + 7) % 7> <!-- 当月第一个周一的日期 --> <#local thirdMonday = firstMonday + 14> <#if day == thirdMonday> <#return true> </#if> </#if> <!-- 3. 总统日(2月第三个周一) --> <#if month == 2> <#local firstMonday = 1 + (2 - dayOfWeek + 7) % 7> <#local thirdMonday = firstMonday + 14> <#if day == thirdMonday> <#return true> </#if> </#if> <!-- 4. 阵亡将士纪念日(5月最后一个周一) --> <#if month == 5> <#local lastDayOfMay = 31> <#local lastDayOfWeek = (date?date("yyyy-MM-31")?day_of_week)> <#local lastMonday = lastDayOfMay - (lastDayOfWeek - 2 + 7) % 7> <#if day == lastMonday> <#return true> </#if> </#if> <!-- 5. 独立日(7月4日,周末则调休到周一/周五) --> <#if (month ==7 && day ==4) || (month ==7 && day ==3 && dayOfWeek ==7) || (month ==7 && day ==5 && dayOfWeek ==2)> <#return true> </#if> <!-- 6. 劳动节(9月第一个周一) --> <#if month ==9> <#local firstMonday = 1 + (2 - dayOfWeek +7) %7> <#if day == firstMonday> <#return true> </#if> </#if> <!-- 7. 哥伦布日(10月第二个周一) --> <#if month ==10> <#local firstMonday =1 + (2 - dayOfWeek +7) %7> <#local secondMonday = firstMonday +7> <#if day == secondMonday> <#return true> </#if> </#if> <!-- 8. 退伍军人节(11月11日,周末调休) --> <#if (month ==11 && day ==11) || (month ==11 && day ==10 && dayOfWeek ==7) || (month ==11 && day ==12 && dayOfWeek ==2)> <#return true> </#if> <!--9. 感恩节(11月第四个周四) --> <#if month ==11> <#local firstThursday =1 + (5 - dayOfWeek +7) %7> <!-- 周四对应day_of_week=5 --> <#local fourthThursday = firstThursday +21> <#if day == fourthThursday> <#return true> </#if> </#if> <!--10. 圣诞节(12月25日,周末调休) --> <#if (month ==12 && day ==25) || (month ==12 && day ==24 && dayOfWeek ==7) || (month ==12 && day ==26 && dayOfWeek ==2)> <#return true> </#if> <!-- 非节假日 --> <#return false> </#function>
步骤2:修改getPreviousBusinessDay函数,加入节假日校验
修改原函数,让它递归调用自身,直到返回的日期既不是周末也不是节假日:
<#function getPreviousBusinessDay date> <#local dateAsEpochMS = date?long> <#local outieDate> <#local dayOfWeek = date?day_of_week> <!-- 1=周日, 2=周一, ...,7=周六 --> <#if dayOfWeek == 2> <!-- 周一 --> <#local outieDate = (dateAsEpochMS - 3*86400000)?number_to_date> <#elseif dayOfWeek == 1> <!-- 周日 --> <#local outieDate = (dateAsEpochMS - 2*86400000)?number_to_date> <#else> <!-- 周二到周六 --> <#local outieDate = (dateAsEpochMS - 86400000)?number_to_date> </#if> <!-- 检查是否是节假日,如果是则递归调用继续往前推 --> <#if isUSHoliday(outieDate)> <#return getPreviousBusinessDay(outieDate)> <#else> <#return outieDate?string("MMMM d, YYYY")> </#if> </#function>
测试示例
比如,如果July 29, 2022是公司节假日,调用:
${getPreviousBusinessDay("August 1, 2022"?date)}
函数会先返回July 29, 2022,检测到是节假日后,继续往前推到July 28, 2022(如果该日期不是节假日则返回)。
注意事项
- 你可以根据公司实际认可的节假日调整
isUSHoliday函数里的规则,比如某些公司可能不执行调休,只按实际日期判定节假日。 - 递归调用的方式简单直接,如果需要处理跨多个节假日的极端情况,也可以改用循环逻辑避免栈溢出(不过一般节假日连续不超过2天,递归足够覆盖需求)。
内容的提问来源于stack exchange,提问作者Pretentious Beer
相关产品推荐
相关产品推荐

