【问题标题】:Elapsed time without considering weekends and bank holidays in Java在 Java 中不考虑周末和银行假期的经过时间
【发布时间】:2010-09-10 16:27:10
【问题描述】:

我已经实现了一个运行良好的秒表,但没有考虑到银行假日和周末不应计入总时长。我正在寻找一些开源库,我可以在其中获取经过的时间,传递一个开始瞬间,结束瞬间和一组银行假期(周末不计入)。唯一让我更轻松的库是 net.sf.jtemporal,但我仍然需要扩展功能。 谁能告诉我是否有一些有用的库来获得想要的功能?

【问题讨论】:

    标签: java date time stopwatch elapsed


    【解决方案1】:

    我认为这将是您正在寻找的有效解决方案。它计算经过的时间(假设一个工作日有 24 小时),不计算银行假日和周末:

    /**
     * Calculate elapsed time in milliseconds
     * 
     * @param startTime
     * @param endTime
     * @return elapsed time in milliseconds
     */
    
    protected long calculateElapsedTimeAux(long startTime, long endTime) { 
        CustomizedGregorianCalendar calStartTime = new CustomizedGregorianCalendar(this.getTimeZone());
        CustomizedGregorianCalendar calEndTime = new CustomizedGregorianCalendar(this.getTimeZone());
        calStartTime.setTimeInMillis(startTime);
        calEndTime.setTimeInMillis(endTime);
        long ticks = 0;
    
        while (calStartTime.before(calEndTime)) { // iterate until reaching end 
            ticks = ticks + increaseElapsedTime(calStartTime, calEndTime);
        }
    
        return ticks;
    }
    
    private long increaseElapsedTime(CustomizedGregorianCalendar calStartTime, CustomizedGregorianCalendar calEndTime) {
        long interval;
        long ticks = 0;
    
        interval = HOURS_PER_DAY*MINUTES_PER_HOUR*SECONDS_PER_MIN*MILLISECONDS_PER_SEC; // Interval of one day
    
        if ( calEndTime.getTimeInMillis() - calStartTime.getTimeInMillis() < interval) {
            interval = calEndTime.getTimeInMillis() - calStartTime.getTimeInMillis();
        }
    
        ticks = increaseElapsedTimeAux(calStartTime, calEndTime, interval);
        calStartTime.setTimeInMillis(calStartTime.getTimeInMillis() + interval);
    
        return ticks;
    }
    
    protected long increaseElapsedTimeAux(CustomizedGregorianCalendar calStartTime, CustomizedGregorianCalendar calEndTime, long interval) {
        long ticks = 0;
    
        CustomizedGregorianCalendar calNextStartTime = new CustomizedGregorianCalendar(this.getTimeZone());
        calNextStartTime.setTimeInMillis(calStartTime.getTimeInMillis() + interval);
    
        if ( (calStartTime.isWorkingDay(_nonWorkingDays) && calNextStartTime.isWorkingDay(_nonWorkingDays)) ) { // calStartTime and calNextStartTime are working days
            ticks = interval;
    
        }
        else {
            if (calStartTime.isWorkingDay(_nonWorkingDays)) { // calStartTime is a working day and calNextStartTime is a non-working day
                ticks = (calStartTime.getNextDay().getTimeInMillis() - calStartTime.getTimeInMillis());
            }
            else {
                if (calNextStartTime.isWorkingDay(_nonWorkingDays)) { // calStartTime is a non-working day and calNextStartTime is a working day
                    ticks = (calNextStartTime.getTimeInMillis() - calStartTime.getNextDay().getTimeInMillis());
                }
                else {} // calStartTime and calEndTime are non-working days
            }
        }
    
        return ticks;
    }
    

    【讨论】:

      【解决方案2】:

      正如我提到的there,可能最好和最简单的方法是创建一个包含每天信息的表格(从开始的工作日计数/银行假日等;每天一行 = 每年 365 行)和然后只需使用计数功能 / 适当的选择。

      【讨论】:

      • 抱歉,我编辑了我的问题,指定我使用的语言是 Java。非常感谢。
      【解决方案3】:

      你应该看看Joda Time。它是一种比 Java 中包含的更好的日期/时间 API

      【讨论】:

      • 谢谢,但我已经这样做了,它比 Java 的要好,但无论如何我发现 net.sf.jtemporal 更适合我的目标。使用CompactPeriodStorage.periodIterator(Period period),您可以获得CloseableIterator,它迭代与给定周期相交的所有存储周期。
      【解决方案4】:

      我怀疑你能找到特定的东西。但是创建自己的逻辑很容易。这是一些伪代码...

      private long CalculateTimeSpan(DateTime BeginDate, DateTime EndDate, ArrayList<DateTime> BankHollidays)
      {
          long ticks = 0;
          while (BeginDate <= EndDate) // iterate until reaching end
          {
              if ((BeginDate is holliday?) || (BeginDate is Weekend?))
                   skip;
              else
                   ticks += (24*60*60*1000);
      
              BeginDate = BeginDate + 1 day; // add one day and iterate
          }
      
          return ticks;
      }
      

      【讨论】:

      • 我会使用 HashSet 来避免重复放置值,但在我看来效率有点低,特别是因为如果粒度为秒,您必须每天迭代 60x60x24 次。对于这种情况,还有其他更有效的想法。谢谢
      【解决方案5】:

      您也只计算银行营业时间吗?上午 9 点至下午 3 点?还是一天24小时?

      【讨论】:

      • 一天 24 小时。我得到了经过的计时器,但我想返回该持续时间减去该间隔内的周末和银行假期的持续时间。
      猜你喜欢
      • 2018-02-08
      • 2017-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-03
      • 1970-01-01
      • 2021-09-29
      相关资源
      最近更新 更多