001/*
002 * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
003 *
004 * Based in London, we are world leaders in the design and development
005 * of bespoke applications for the securities financing markets.
006 *
007 * <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
008 *           ___  _     _           _   _          _
009 *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
010 *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
011 *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
012 *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
013 *                   |__/
014 *
015 *                     www.ObjectLab.co.uk
016 *
017 * $Id$
018 *
019 * Copyright 2006 the original author or authors.
020 *
021 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
022 * use this file except in compliance with the License. You may obtain a copy of
023 * the License at
024 *
025 * http://www.apache.org/licenses/LICENSE-2.0
026 *
027 * Unless required by applicable law or agreed to in writing, software
028 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
029 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
030 * License for the specific language governing permissions and limitations under
031 * the License.
032 */
033package net.objectlab.kit.datecalc.common;
034
035import java.util.Calendar;
036import java.util.Date;
037
038/**
039 * Immutable Working Week, default is Mon-&gt;Friday.
040 *
041 * @author Benoit Xhenseval
042 *
043 */
044public class WorkingWeek {
045    private static final byte MONDAY = 1;
046
047    private static final byte TUESDAY = 2;
048
049    private static final byte WEDNESDAY = 4;
050
051    private static final byte THURSDAY = 8;
052
053    private static final byte FRIDAY = 16;
054
055    private static final byte SATURDAY = 32;
056
057    private static final byte SUNDAY = 64;
058
059    private static final byte DEFAULT_WORKING_DAYS = (byte) (MONDAY + TUESDAY + WEDNESDAY + THURSDAY + FRIDAY);
060
061    private static final byte ARABIC_WORKING_DAYS = (byte) (MONDAY + TUESDAY + WEDNESDAY + THURSDAY + SUNDAY);
062
063    private static final byte[] WORKING_WEEK_DAYS_OFFSET = new byte[] { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY };
064
065    public static final WorkingWeek DEFAULT = new WorkingWeek();
066
067    public static final WorkingWeek ARABIC_WEEK = new WorkingWeek(ARABIC_WORKING_DAYS);
068
069    // -----------------------------------------------------------------------
070    //
071    // ObjectLab, world leaders in the design and development of bespoke
072    // applications for the securities financing markets.
073    // www.ObjectLab.co.uk
074    //
075    // -----------------------------------------------------------------------
076
077    /**
078     * working days: 1 Monday, 2 Tuesday, 4 Wednesday, 8 Thursday, 16 Friday, 32
079     * Saturday, 64 Sunday So Monday-Friday= 1+2+4+8+16 = 31
080     */
081    private byte workingDays = DEFAULT_WORKING_DAYS;
082
083    /**
084     * Default Working Week Monday -&gt; Friday.
085     */
086    public WorkingWeek() {
087        this(DEFAULT_WORKING_DAYS);
088    }
089
090    protected WorkingWeek(final byte workingDays) {
091        this.workingDays = workingDays;
092    }
093
094    /**
095     * Create a new calendar with the intersection of WORKING days.
096     * e.g. if normal and arabic calendars are intersected, the week is 3 days: Fri-Sun.
097     * @param ww
098     * @return a new Working week
099     * @since 1.4.0
100     */
101    public WorkingWeek intersection(final WorkingWeek ww) {
102        final byte combined = (byte) (this.workingDays & ww.workingDays);
103        return new WorkingWeek(combined);
104    }
105
106    public boolean isWorkingDayFromCalendar(final int dayOfWeek) {
107        final int day = adjustDay(dayOfWeek);
108        return (WORKING_WEEK_DAYS_OFFSET[day] & workingDays) != 0;
109    }
110
111    public boolean isWorkingDay(final Date date) {
112        return isWorkingDay(Utils.getCal(date));
113    }
114
115    public boolean isWorkingDay(final Calendar cal) {
116        return isWorkingDayFromCalendar(cal.get(Calendar.DAY_OF_WEEK));
117    }
118
119    protected int adjustDay(final int dayOfWeek) {
120        return dayOfWeek - 1;
121    }
122
123    /**
124     * If the value for the given day has changed, return a NEW WorkingWeek.
125     *
126     * @param working
127     *            true if working day
128     * @param dayOfWeek
129     *            e.g. Calendar.MONDAY, Calendar.TUESDAY, etc
130     * @return a new instance of a <code>WorkingWeek</code> with the working
131     *         day set
132     */
133    public WorkingWeek withWorkingDayFromCalendar(final boolean working, final int dayOfWeek) {
134        final int day = adjustDay(dayOfWeek);
135        WorkingWeek ret = this;
136        if (working && !isWorkingDayFromCalendar(dayOfWeek)) {
137            ret = new WorkingWeek((byte) (workingDays + WORKING_WEEK_DAYS_OFFSET[day]));
138        } else if (!working && isWorkingDayFromCalendar(dayOfWeek)) {
139            ret = new WorkingWeek((byte) (workingDays - WORKING_WEEK_DAYS_OFFSET[day]));
140        }
141        return ret;
142    }
143
144    public byte getWorkingDays() {
145        return workingDays;
146    }
147}
148
149/*
150 * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
151 *
152 * Based in London, we are world leaders in the design and development
153 * of bespoke applications for the securities financing markets.
154 *
155 * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
156 *           ___  _     _           _   _          _
157 *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
158 *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
159 *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
160 *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
161 *                   |__/
162 *
163 *                     www.ObjectLab.co.uk
164 */