ucAdjustWorkdays

Purpose

This is used to allow special date arithmetic. A true value is returned if a change has been made.

Applies To

Add Issue screen

Signature

 public boolean ucAdjustWorkdays (int action, DateCalculator dc)

Notes

Example

// Setup global vars used by ucAdjustWorkdays

Calendar [] holidays = null;
static final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;

// Setup methods used by ucAdjustWorkdays

int myCompare (Calendar c1, Calendar c2) {
    // Note: This looks like it's trying to get the same day
    // by dividing by MILLIS_PER_DAY,
    // but that can cross date boundaries;
    // probably due to the TZ offset, don't want to change this 
    // at the moment as it seeems to wrork for what is needed.
    long t1 = c1.getTimeInMillis() / MILLIS_PER_DAY;
    long t2 = c2.getTimeInMillis() / MILLIS_PER_DAY;
    if (t1 > t2)      { return 1;  }
    else if (t1 < t2) { return -1; }
    
    return 0;
}


void backupOneBusinessDay (Calendar st, Calendar start)
{
    st.add(Calendar.DATE, -1);
    start.add(Calendar.DATE, -1);

    if (st.get(Calendar.DAY_OF_WEEK) > 6) {    // saturday
      st.add(Calendar.DATE, -1);
      start.add(Calendar.DATE, -1);
    }
    if (st.get(Calendar.DAY_OF_WEEK) == 1) {    // sunday
      st.add(Calendar.DATE, -2);
      start.add(Calendar.DATE, -2);
    }
}


void advanceOneBusinessDay (Calendar st, Calendar start)
{
    st.add(Calendar.DATE, 1);
    start.add(Calendar.DATE, 1);

    if (st.get(Calendar.DAY_OF_WEEK) == 7) {    // saturday
      st.add(Calendar.DATE, 2);
      start.add(Calendar.DATE, 2);
    }
    if (st.get(Calendar.DAY_OF_WEEK) == 1) {    // sunday
      st.add(Calendar.DATE, 1);
      start.add(Calendar.DATE, 1);
    }
}


public void setHolidays (Connection con, SesameSession session)
throws Exception
{
    holidays = new Calendar[9];
    
    DbTime t =  new DbTime(session, con);
    Calendar c = t.getUserNow() ;
    int i = 0;
    
    c.set(Calendar.AM_PM, Calendar.PM);
    // New Year’s Day  Friday, January 1, 2010
    c.set(2010, 0, 1, 0, 0,  0);
    c.set(Calendar.MILLISECOND, 0);
    c.add(Calendar.DATE, 1);
    c.add(Calendar.DATE, -1);
    holidays[i++] = (Calendar) c.clone();
    
    // President’s Day  Monday, February 15, 2010
    c.set(2010, 1, 15);
    c.add(Calendar.DATE, 1);
    c.add(Calendar.DATE, -1);
    holidays[i++] = (Calendar) c.clone();
    
    // Memorial Day  Monday, May 31, 2010
    c.set(2010, 4, 31);
    c.add(Calendar.DATE, 1);
    c.add(Calendar.DATE, -1);
    holidays[i++] = (Calendar) c.clone();
    
    // Independence Day  Monday, July 5, 2010
    c.set(2010, 6,  5);
    c.add(Calendar.DATE, 1);
    c.add(Calendar.DATE, -1);
    holidays[i++] = (Calendar) c.clone();
    
    // Labor Day  Monday, September 6, 2010
    c.set(2008, 8,  6);
    c.add(Calendar.DATE, 1);
    c.add(Calendar.DATE, -1);
    holidays[i++] = (Calendar) c.clone();
    
    // Thanksgiving Day  Thursday, November 25, 2010
    c.set(2010,10, 25);
    c.add(Calendar.DATE, 1);
    c.add(Calendar.DATE, -1);
    holidays[i++] = (Calendar) c.clone();
    
    // Day after Thanksgiving  Friday, November 26, 2010
    c.set(2010,10, 26);
    c.add(Calendar.DATE, 1);
    c.add(Calendar.DATE, -1);
    holidays[i++] = (Calendar) c.clone();
    
    // Christmas Eve  Friday, December 24, 2010
    c.set(2010,11, 24);
    c.add(Calendar.DATE, 1);
    c.add(Calendar.DATE, -1);
    holidays[i++] = (Calendar) c.clone();
    
    // Christmas Day Monday, December 27, 2010
    c.set(2010,11, 27);
    c.add(Calendar.DATE, 1);
    c.add(Calendar.DATE, -1);
    holidays[i++] = (Calendar) c.clone();
    
    // for (i=0; i < holidays.length; i++) w("holiday[" + i + "]: " + dmpD(holidays[i]));
}


public boolean ucAdjustWorkdays (int action, DateCalculator dc)
throws Exception
{
    boolean changed = false;
    
    if (holidays == null)
    {
        SesameSession session = SesameSession.getSession();
        Connection con = null;
        
        try {
            con = Z.pool.getConnection("ucAdjustWorkdays");
            setHolidays (con, session);
            
        } catch (Exception e) {
            holidays = null;
            Z.log.writeToLog(Z.log.ERROR, "UC: ucAdjustWorkdays Exception: " + e);
            ErrorWriter.write(e, ErrorWriter.LOGERR);
            
        } finally {
            if (con != null) { Z.pool.close(con); }
        }
    }
    
    Calendar start = dc.getStartDate();
    Calendar end = dc.getEndDate();
    double interval = dc.getInterval();
    boolean isReversed = false;
    // w("action ==? : " + (action == DateCalculator.SET_INTERVAL));
    // if we're setting the interval, check for holidays inside...
    if (action == DateCalculator.SET_INTERVAL)
    {
        if (start.before(end)) {
            Calendar t = start;
            start = end;
            end = t;
            interval = - interval;
            isReversed = true;
        }
        
        for (int i=0; i < holidays.length; i++)
        {
            // w("holiday: " + dmpD(holidays[i]) + "; start: " + dmpD(start) +
            // "; end: " + dmpD(end) + "; mycomp: " + myCompare(start, holidays[i]) +
            // "; comp2: " + myCompare(end, holidays[i]));
            if (!start.before(holidays[i]) && !end.after(holidays[i])) {
                interval -= 1.d;
            }
        }
        
        if (isReversed) { interval = - interval; }
        
        if (dc.getInterval() != interval) {
            dc.setInterval(interval);
            return true;
        }
        
        return false;
    }
        
    // 
    if (dc.getInterval() == 0.d) { return false; }
    
    // w("start: " + dmpD(start) +"; end: " + dmpD(end) + "; interval: " + interval);
    // workaound for rules bug passing in interval with wrong sign in 6.0.1 code.
    // this can be removed in 6.1.
    if (start.after(end) && interval > 0.d || start.before(end) && interval < 0.d ) {
        interval = -interval;
    }
    
    Calendar st = (Calendar) start.clone();
    st.set(Calendar.AM_PM, Calendar.PM);
    st.set(Calendar.HOUR, 0);
    st.set(Calendar.MINUTE, 0);
    st.set(Calendar.SECOND, 0);
    st.set(Calendar.MILLISECOND, 0);
    st.add(Calendar.DATE, 1);
    st.add(Calendar.DATE, -1);
    
    Calendar en = (Calendar) end.clone();
    en.set(Calendar.AM_PM, Calendar.PM);
    en.set(Calendar.HOUR, 0);
    en.set(Calendar.MINUTE, 0);
    en.set(Calendar.SECOND, 0);
    en.set(Calendar.MILLISECOND, 0);
    en.add(Calendar.DATE, 1);
    en.add(Calendar.DATE, -1);
    
    // if these are reversed, then swap the dates
    // for comparison, so the first date is always
    // before the second.  when we adjust below,
    // we take this into account.
    boolean reversed = en.before(st);
    
    if (reversed) {
        Calendar h = st;
        st = en;
        en = h;
    }

    int s = -1;
    int e = -1;

    for (int i=0; i= 0 ) {
            s = i;
            break;
        }
    }

    // if all holidays are before start date, nothing to do.    
    if (s == -1) { return false; }

    for (int i= holidays.length; i-- > 0;) {
        if (myCompare (holidays[i], en) <= 0) {
            e = i;
            break;
        }
    }
    
    if (e < s) { return false; }    // no holidays in between
    
    // number of holidays is the number in between
    int num = e - s + 1;
    
    // step through adding the days one at a time so we
    // can skip over additional holidays or weekends
    // as we go.  note that we are adjusting the date in the date calculator
    // which is actually a reference (pointer) to the original
    // object, so we are always adjusting the end date
    for (int i=0; i 0 && myCompare (st, holidays[s-1]) == 0  ) {
                s--;
                num++;
            }
        }
        else
        {
            advanceOneBusinessDay(en, end);
            // if new day is a holiday, skip another one.
            if (e < holidays.length && myCompare(en, holidays[e+1]) == 0 ) {
                num++;
                e++;
            }
        }
    }
    
    return changed;
}