判断工作日的方法

楼主
我是社区第55902位番薯,欢迎点我头像关注我哦~
我们说的工作日和休息日一共有3个条件~
1.我们自己所在公司定义的特殊工作日和休息日(即便是公休日,但是公司可能会调休)
2.国家规定的节假日(元旦 春节 清明 端午 等等的)
3.公休日(周六,周天)

我们要具体计算某一天是否是工作日还是休息日,比较麻烦的就是获取国家规定的节假日的各种调休比较麻烦。以前有一个工作日插件~但是我看了一下他用的是一个服务接口来获取这个每年的节假日情况~那个接口服务商已经关闭了~另外网上其他的节假日服务商要么要收费,要么就不准(他会把免费的故意弄几个错误值在里面,我一共找了7个这种接口都是这样,要么要收钱,要么有错误)~所以我自己弄了一个方法~直接到国务院官网上去爬每年的节假日安排就好了~
PS:当然我们还有一个办法就是自己建个数据库,手动把这些数据输入进去也可以
不说了先看效果


然后 看代码
数据是保存在XML里面的所以有一个数据管理类
  1. package com.midas.plugin.func;

  2. import java.text.SimpleDateFormat;
  3. import java.util.ArrayList;
  4. import java.util.Calendar;
  5. import java.util.Date;
  6. import java.util.List;
  7. import java.util.Set;

  8. import com.fr.base.FRContext;
  9. import com.fr.file.XMLFileManager;
  10. import com.fr.function.TODATE;
  11. import com.fr.general.GeneralContext;
  12. import com.fr.general.xml.GeneralXMLTools;
  13. import com.fr.json.JSONArray;
  14. import com.fr.json.JSONObject;
  15. import com.fr.stable.EncodeConstants;
  16. import com.fr.stable.EnvChangedListener;
  17. import com.fr.stable.xml.XMLPrintWriter;
  18. import com.fr.stable.xml.XMLableReader;

  19. public class DateRecord extends XMLFileManager {
  20.         
  21.         private JSONObject conf = JSONObject.create();
  22.         
  23.         public Date toDate( Object dtObj ){
  24.                 return (Date) new TODATE().run(new Object[]{dtObj});
  25.         }
  26.         
  27.         public boolean isHoliday(Date dt){
  28.                 return isHoliday(dt,true,true);
  29.         }
  30.         
  31.         public boolean isHoliday(Date dt, boolean useGov){
  32.                 return isHoliday(dt,useGov,true);
  33.         }
  34.         
  35.         public boolean isHoliday(Date dt, boolean useGov, boolean useDef ){
  36.                 String year = getYear(dt);
  37.                 String dtStr = WorkDay.getDateStr(dt);
  38.                 //从自定义数据判断
  39.                 JSONObject custom = getCustom(year);
  40.                 int cr = isHoliday(custom,dtStr);
  41.                 if(cr!=-1){
  42.                         return cr == 1;
  43.                 }
  44.                 //从国务院数据判断
  45.                 if(useGov){
  46.                         JSONObject locale = getLocale(year);
  47.                         int lr = isHoliday(locale,dtStr);
  48.                         if(lr!=-1){
  49.                                 return lr == 1;
  50.                         }
  51.                 }
  52.                 //直接判断是否是周末
  53.                 if(useDef){
  54.                         Calendar cal = Calendar.getInstance();
  55.                         cal.setTime(dt);
  56.                         int w = cal.get(Calendar.DAY_OF_WEEK);
  57.                         return w==1 || w==7;
  58.                 }
  59.                 return false;
  60.         }
  61.         
  62.         public int getHolidayCount(Date start,Date end){
  63.                 int sy = Integer.parseInt(getYear(start));
  64.                 int ey = Integer.parseInt(getYear(end));
  65.                 int sdn = Integer.parseInt(WorkDay.getDateStr(start));
  66.                 int edn = Integer.parseInt(WorkDay.getDateStr(end));
  67.                 int count = 0;
  68.                 for(int i=sy;i<=ey;i++){
  69.                         JSONArray chJa = getCustom(i+"").optJSONArray("h");
  70.                         String ch = chJa.toString();
  71.                         String cw = getCustom(i+"").optJSONArray("w").toString();
  72.                         JSONArray dJa = getDefaultHoliday(i+"");
  73.                         for(int j=0;j<dJa.length();j++){
  74.                                 int cDt = Integer.parseInt(dJa.optString(j));
  75.                                 if( sdn <= cDt && cDt <= edn && cw.indexOf(cDt+"")==-1 && ch.indexOf(cDt+"")==-1 ){
  76.                                         count++;
  77.                                 }
  78.                         }
  79.                         JSONArray hJa = getLocale(i+"").optJSONArray("h");
  80.                         for(int j=0;j<hJa.length();j++){
  81.                                 int cDt = Integer.parseInt(hJa.optString(j));
  82.                                 if( sdn <= cDt && cDt <= edn && cw.indexOf(cDt+"")==-1 && ch.indexOf(cDt+"")==-1 ){
  83.                                         count++;
  84.                                 }
  85.                         }
  86.                         for(int j=0;j<chJa.length();j++){
  87.                                 int cDt = Integer.parseInt(chJa.optString(j));
  88.                                 if( sdn <= cDt && cDt <= edn ){
  89.                                         count++;
  90.                                 }
  91.                         }
  92.                 }
  93.                 return count;
  94.         }
  95.         
  96.         /**
  97.          * 生成一年内全部的周末假日
  98.          * @param year
  99.          */
  100.         private JSONArray getDefaultHoliday(String year){
  101.                 JSONObject locale = this.getLocale(year);
  102.                 if(locale.has("d")){
  103.                         return locale.optJSONArray("d");
  104.                 }
  105.                 String hJa = locale.optJSONArray("h").toString();
  106.                 String wJa = locale.optJSONArray("w").toString();
  107.                 Date[] wkd = getFirstWKD(year);
  108.                 JSONArray dfthwkd = JSONArray.create();
  109.                 Date sd = wkd[wkd.length-1];
  110.                 if( wkd.length==2 ){
  111.                         String dStr = WorkDay.getDateStr(wkd[0]);
  112.                         if( wJa.indexOf(dStr)==-1 && hJa.indexOf(dStr)==-1 ){
  113.                                 dfthwkd.put(dStr);
  114.                         }
  115.                 }
  116.                 Calendar cal = Calendar.getInstance();
  117.                 while( getYear(sd).equals(year) ){
  118.                         String dStr = WorkDay.getDateStr(sd);
  119.                         if( wJa.indexOf(dStr)==-1 && hJa.indexOf(dStr)==-1 ){
  120.                                 dfthwkd.put(dStr);
  121.                         }
  122.                         cal.setTime(sd);
  123.                         cal.add(Calendar.DATE, 6);
  124.                         sd = cal.getTime();
  125.                         if( !getYear(sd).equals(year) ){
  126.                                 break;
  127.                         }
  128.                         dStr = WorkDay.getDateStr(sd);
  129.                         if( wJa.indexOf(dStr)==-1 && hJa.indexOf(dStr)==-1 ){
  130.                                 dfthwkd.put(dStr);
  131.                         }
  132.                         cal.setTime(sd);
  133.                         cal.add(Calendar.DATE, 1);
  134.                         sd = cal.getTime();
  135.                 }
  136.                 try{
  137.                         locale.put("d",dfthwkd);
  138.                         FRContext.getCurrentEnv().writeResource(this);
  139.                 }catch(Exception e){}
  140.                 return locale.optJSONArray("d");
  141.         }
  142.         
  143.         /**
  144.          * 获取某年的第一个周末
  145.          * @param year
  146.          * @return
  147.          */
  148.         private Date[] getFirstWKD(String year){
  149.                 Date[] rt = null;
  150.                 Calendar cal = Calendar.getInstance();
  151.                 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
  152.                 try{
  153.                         Date firstDay = format.parse(year+"0101");
  154.                         cal.setTime(firstDay);
  155.                         int w = cal.get(Calendar.DAY_OF_WEEK);
  156.                         while( w!=1 && w!=7 ){
  157.                                 cal.add(Calendar.DATE, 1);
  158.                                 w = cal.get(Calendar.DAY_OF_WEEK);
  159.                         };
  160.                         if(w==7){
  161.                                 rt = new Date[2];
  162.                                 rt[0] = cal.getTime();
  163.                                 cal.add(Calendar.DATE, 1);
  164.                                 rt[1] = cal.getTime();
  165.                         }else if(w==1){
  166.                                 rt = new Date[1];
  167.                                 rt[0] = cal.getTime();
  168.                         }
  169.                 }catch(Exception e){}
  170.                 return rt;
  171.         }
  172.         
  173.         private int isHoliday(JSONObject plan,String dtStr){
  174.                 String lh = plan.optJSONArray("h").toString();
  175.                 if(lh.indexOf(dtStr)!=-1){
  176.                         return 1;
  177.                 }
  178.                 String lw = plan.optJSONArray("w").toString();
  179.                 if(lw.indexOf(dtStr)!=-1){
  180.                         return 0;
  181.                 }
  182.                 return -1;
  183.         }
  184.         
  185.         private String getYear(Date dt){
  186.                 SimpleDateFormat format = new SimpleDateFormat("yyyy");
  187.                 String dtStr = format.format(dt);
  188.                 return dtStr;
  189.         }
  190.         private JSONObject opt(String key){
  191.                 try{
  192.                         if(!conf.has(key)){
  193.                                 conf.put(key, JSONObject.create());
  194.                         }
  195.                 }catch(Exception e){}
  196.                 return conf.optJSONObject(key);
  197.         }
  198.         
  199.         private JSONObject getCustom(String year){
  200.                 JSONObject custom = opt("custom");
  201.                 if(!custom.has(year)){
  202.                         try{
  203.                                 custom.put(year,JSONObject.create().put("h", JSONArray.create()).put("w", JSONArray.create()));
  204.                         }catch(Exception e){}
  205.                 }
  206.                 return custom.optJSONObject(year);
  207.         }
  208.         
  209.         private JSONObject getLocale(String year){
  210.                 JSONObject locale = opt("locale");
  211.                 if(!locale.has(year)){
  212.                         loadWebHoliday( year );
  213.                 }
  214.                 return locale.optJSONObject(year);
  215.         }
  216.         
  217.         private JSONObject loadWebHoliday( String year ){
  218.                 try{
  219.                         JSONObject result = JSONObject.create();
  220.                         List<String> wDateList = new ArrayList<String>();
  221.                         List<String> hDateList = new ArrayList<String>();
  222.                         //从国务院官网下载某一年的节假日安排情况
  223.                         WorkDay.loadHolidayPlanFromGov(year, wDateList, hDateList);
  224.                         JSONArray wJa = JSONArray.create();
  225.                         JSONArray hJa = JSONArray.create();
  226.                         for(String d : wDateList ){
  227.                                 wJa.put(d);
  228.                         }
  229.                         for(String d : hDateList ){
  230.                                 hJa.put(d);
  231.                         }
  232.                         result.put("w", wJa);
  233.                         result.put("h", hJa);
  234.                         conf.optJSONObject("locale").put(year, result);
  235.                         FRContext.getCurrentEnv().writeResource(this);
  236.                 }catch(Exception e){}
  237.                 return conf;
  238.         }
  239.         
  240.         private static final long serialVersionUID = 4378324674935440870L;
  241.         private static DateRecord SE = null;
  242.         
  243.         private DateRecord(){
  244.                 readXMLFile();
  245.         }
  246.         
  247.         public synchronized static DateRecord getInstance(){
  248.                 if( null == SE ){
  249.                         SE = new DateRecord();
  250.                 }
  251.                 return SE;
  252.         }
  253.         
  254.         static {
  255.         GeneralContext.addEnvChangedListener(new EnvChangedListener() {
  256.             public void envChanged() {
  257.                     DateRecord.envChanged();
  258.             }
  259.         });
  260.     }

  261.     private synchronized static void envChanged() {
  262.         SE = null;
  263.     }
  264.         
  265.         @Override
  266.         public String fileName() {
  267.                 return "holiday.xml";
  268.         }

  269.         @Override
  270.         public void writeXML(XMLPrintWriter writer) {
  271.                 writer.startTAG("Conf");
  272.                 writer.startTAG("Custom");
  273.                 try{
  274.                         Set<String> years = opt("custom").toMap().keySet();
  275.                         for(String year : years ){
  276.                                 JSONObject yJo = opt("custom").optJSONObject(year);
  277.                                 JSONArray hJa = yJo.optJSONArray("h");
  278.                                 for(int i=0;i<hJa.length();i++){
  279.                                         writer.startTAG("item").attr("dt", hJa.optString(i)).attr("type", "h").end();
  280.                                 }
  281.                                 JSONArray wJa = yJo.optJSONArray("w");
  282.                                 for(int i=0;i<wJa.length();i++){
  283.                                         writer.startTAG("item").attr("dt", wJa.optString(i)).attr("type", "w").end();
  284.                                 }
  285.                         }
  286.                 }catch(Exception e){}
  287.                 writer.end();
  288.                         
  289.                 writer.startTAG("Locale");
  290.                 try{
  291.                         GeneralXMLTools.writeByteArray(writer, conf.optJSONObject("locale").toString().getBytes(EncodeConstants.ENCODING_UTF_8));
  292.                 }catch(Exception e){}
  293.                 writer.end();
  294.                
  295.                 writer.end();
  296.         }
  297.         
  298.         @Override
  299.         public void readXML(XMLableReader reader) {
  300.                 String tagname = reader.getTagName();
  301.                 if("Locale".equals( tagname )){
  302.                         try{
  303.                                 String value = new String(GeneralXMLTools.readByteArray(reader), EncodeConstants.ENCODING_UTF_8);
  304.                                 JSONObject locale = new JSONObject(value);
  305.                                 conf.put("locale", locale);
  306.                         }catch(Exception e){}
  307.                 }else if("item".equals( tagname )){
  308.                         String dt = reader.getAttrAsString("dt", "");
  309.                         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
  310.                         String type = reader.getAttrAsString("type", "");
  311.                         try{
  312.                                 if(!"h".equals(type)&&!"w".equals(type)){
  313.                                         return ;
  314.                                 }
  315.                                 String year = getYear(format.parse(dt));
  316.                                 JSONObject yJa = getCustom(year);
  317.                                 yJa.optJSONArray(type).put(dt);
  318.                         }catch(Exception e){}
  319.                 }
  320.         }

  321. }
复制代码
然后就是两个自定义函数了,一个判断是不是休息日,一个获取工作日或者休息日数量
  1. package com.midas.plugin.func;

  2. import java.util.Date;

  3. import com.fr.script.AbstractFunction;

  4. public class IsHoliday extends AbstractFunction {
  5.         public static void main(String[]args){
  6.                 new com.fr.start.Designer(null);
  7.         }
  8.         private static final long serialVersionUID = 2940754222244608301L;

  9.         @Override
  10.         public Object run(Object[] params) {
  11.                 if(params.length == 1){
  12.                         return DateRecord.getInstance().isHoliday((Date) params[0]);
  13.                 }
  14.                 if(params.length == 2){
  15.                         return DateRecord.getInstance().isHoliday((Date) params[0],(Boolean)params[1]);
  16.                 }
  17.                 if(params.length == 3){
  18.                         return DateRecord.getInstance().isHoliday((Date) params[0],(Boolean)params[1],(Boolean)params[2]);
  19.                 }
  20.                 return null;
  21.         }

  22. }
复制代码
  1. package com.midas.plugin.func;

  2. import java.util.Date;

  3. import com.fr.script.AbstractFunction;

  4. @SuppressWarnings("serial")
  5. public class WHDateDif extends AbstractFunction {
  6.         
  7.         private int getDif(Date start,Date end){
  8.                 int days = (int) ((end.getTime() - start.getTime()) / (1000*3600*24));
  9.                 return days+1;
  10.         }
  11.         
  12.         @Override
  13.         public Object run(Object[] params) {
  14.                 Date start = WorkDay.format((Date)params[0]);
  15.                 Date end =  WorkDay.format((Date)params[1]);
  16.                 if( 2==params.length ){
  17.                         return getDif( start, end) - DateRecord.getInstance().getHolidayCount(start, end);
  18.                 }
  19.                 String type = (String)params[2];
  20.                 if( "h".equals(type) ){
  21.                         return DateRecord.getInstance().getHolidayCount(start, end);
  22.                 }
  23.                 return getDif( start, end) - DateRecord.getInstance().getHolidayCount(start, end);
  24.         }

  25. }
复制代码
下面是10-18年的缓存数和需要用到的JAR包
holiday.xml (3.4 KB, 下载次数: 23)
jsoup-1.10.1.jar (337.49 KB, 下载次数: 14)
核心类~获取每年的节假日安排情况的爬虫代码不提供,方法很简单,就是到国务院官网爬放假的公告,然后通过正则表达式解析出里面的节假日就可以了,有兴趣的可以自己研究研究~实在研究不出来的加我的报表群交流



编辑于 2018-4-11 18:26  
分享扩散:

沙发
发表于 2018-4-11 18:31:28
来自手机
给迈神盖楼,小白粉抢沙发
板凳
发表于 2018-4-12 08:49:23
犀利
地板
发表于 2018-4-12 08:51:09
高手高手,点金手
5楼
发表于 2018-4-12 09:03:07
师傅666
6楼
发表于 2018-4-12 12:57:18
1连梦碧
7楼
发表于 2018-4-12 13:09:10
2连梦碧
8楼
发表于 2018-4-26 13:39:54
3连梦碧
9楼
发表于 2018-6-21 13:16:08
不错不错 请问如何使用啊~
10楼
发表于 2018-6-21 13:20:50
gebilaowang 发表于 2018-6-21 13:16
不错不错 请问如何使用啊~

把这几个类编译了放到你的classes下或者整成插件或者JAR包~通过自定义函数或者插件函数~xml放到resources里面~就可以了~核心的爬虫类~要么自己写一个要么去掉用固定的(只到18年~19年的需要等国务院发布新的公告然后自己做爬虫)
11楼
发表于 2018-7-4 17:25:32
辛苦了。好东西
12楼
发表于 2018-7-5 08:23:53
我们公司有自己的作息表,如何使用?
13楼
发表于 2018-7-5 09:21:57
yuanding 发表于 2018-7-5 08:23
我们公司有自己的作息表,如何使用?

配置到附件的xml里面去~xml里面有具体的格式~如果是批量的话~最好用报表拼出xml文本来复制进去即可~
14楼
发表于 2018-7-20 16:40:10
膜拜啊 大佬的传说
15楼
发表于 2019-6-3 17:20:52
看不懂 但是知道很厉害哦
16楼
发表于 2020-10-28 15:22:42
可以分享一下如何爬取国家法定假日么
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

15回帖数 2关注人数 13064浏览人数
最后回复于:2020-10-28 15:22

返回顶部 返回列表