001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.hayabusa.taglib;
017
018import org.opengion.hayabusa.common.HybsSystem;
019import org.opengion.hayabusa.common.HybsSystemException;
020import org.opengion.hayabusa.resource.CalendarData;
021import org.opengion.hayabusa.resource.CalendarFactory;
022import org.opengion.hayabusa.html.ViewStackTableParam;
023import org.opengion.fukurou.util.StringUtil;
024import org.opengion.fukurou.util.HybsDateUtil;
025
026import static org.opengion.fukurou.util.StringUtil.nval ;
027
028import java.util.Calendar;
029import java.util.Date;
030import java.util.List;
031import java.util.ArrayList;
032import java.util.Locale ;
033import java.text.DateFormat;
034import java.text.SimpleDateFormat;
035
036/**
037 * ガントチャート用のヘッダー情報(日付け等)を出力するタグです。
038 *
039 * スライドバー式ガントチャートの表示時に、スライドバーの長さと日付とを関連付けるための
040 * ヘッダー情報(日付け等)を出力します。スライドバーと日付間隔は、zoom 属性によって、
041 * CSSファイルのフォントサイズと、JavaScript の内部配列に依存しています。
042 * また、このヘッダーでは、日付の休日情報を、カレンダテーブルを参照することで取得しています。
043 * calDB 属性への指定は、CalendarFactory で生成されるテーブル名(CalendarDataの実装クラス)
044 * を指定します。
045 *
046 * @og.formSample
047 * ●形式:<og:ganttHeader startDate="…" endDate="…" zoom="[…]" />
048 * ●body:なし
049 *
050 * ●Tag定義:
051 *   <og:ganttHeader
052 *       startDate          【TAG】表示開始日付けを設定します(yyyyMMdd または、yyyyMMddHHmm 形式)
053 *       endDate            【TAG】表示最終日を設定します(yyyyMMdd または、yyyyMMddHHmm 形式)
054 *       zoom               【TAG】ズーム変数(0〜13,20〜31,40〜49)を設定します(初期値:2)
055 *       calDB              【TAG】DB検索するDBを指定します
056 *       arg1               【TAG】DB検索する場合の第1のキーを指定します
057 *       arg2               【TAG】DB検索する場合の第2のキーを指定します
058 *       arg3               【TAG】DB検索する場合の第3のキーを指定します
059 *       arg4               【TAG】DB検索する場合の第4のキーを指定します
060 *       daySpan            【TAG】1日の開始終了時間を24時間形式(HHmm-HHmm)で設定します(初期値:0700-2000)
061 *       breakTimes         【TAG】時間軸での休憩時間の開始-終了時刻をカンマ区切りで複数指定します(HHmm-HHmm形式、または、yyyyMMddHHmm-HHmm形式、または、yyyyMMddHHmm-yyyyMMddHHmm形式)
062 *       breakTimeStyle     【TAG】時間軸での休憩時間の表示スタイルを設定します(初期値:top:20px;background-color:yellow;filter:alpha(opacity=60);opacity:0.60;)
063 *       baseTimes          【TAG】時間軸でのベース時刻の開始時刻をカンマ区切りで複数指定します(HHmm形式、または、yyyyMMddHHmm形式)
064 *       baseTimeStyle      【TAG】時間軸でのベース時刻の表示スタイルを設定します(初期値:top:20px;background-color:transparent;border-left:2px dashed red;)
065 *       skipHoliday        【TAG】時間ガントで休日を表示する/しないを設定します (初期値:USE_GANTTHEADER_SKIP_HOLIDAY[=true])
066 *       useMultiClm        【TAG】時間ヘッダーの上段に日付を、下段の時間を表示します (初期値:USE_GANTTHEADER_MULTIPLE_COLUMN[=false])
067 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
068 *   />
069 *
070 * ●使用例
071 *    参照:jsp/GANTT06 フォルダ
072 *
073 *     <og:ganttHeader
074 *         startDate = "{@VIEW_DATE}"
075 *         endDate   = "{@DYMAX}"
076 *         zoom      = "{@VIEW_ZOOM}"
077 *         calDB     = "GF13"
078 *         arg1      = "{@CDJGS}"
079 *         arg2      = ""
080 *     /og:ganttHeader>
081 *
082 *     <og:ganttHeader
083 *         startDate  = "{@VIEW_DATE}"
084 *         endDate    = "{@DYMAX}"
085 *         daySpan    = "0700-2000"                               HHmm-HHmm 形式で1日の時間範囲を指定
086 *         breakTimes = "1200-1245,1645-1650,200508200700-1200;"  休憩時間は、HHmm-HHmm形式、または、yyyyMMddHHmm-HHmm形式、または、yyyyMMddHHmm-yyyyMMddHHmm形式です。
087 *         breakTimeStyle = "top:20px;background-color:yellow;"   休憩時間のスタイルに追加します。
088 *         zoom       = "20"
089 *     /og:ganttHeader>
090 *
091 * ●定義・解説
092 *   PL/SQL の VIEW_ZOOM メソッドを用いて、実際の日付けから画面表示ピクセルへ
093 *   変換する割合を求めます。これと、jsp\GANTT\image の ganttBGx.gif(x は ZOOM変数)
094 *   を対応付けて、日付けのヘッダーを求めます。
095 *   jsp\custom\custom.css の th.zoomx(x は ZOOM変数) により、日付けヘッダー文字の
096 *   表示間隔を制御していますので、これらの関係を正確に把握しておいて下さい。
097 *   日付けヘッダーは、イメージ変数を用いている関係上、固定の日数を加算して、
098 *   求めます。(週:7日, 半月:15日, 月:30日, 4半期:90日, 年:360日)
099 *
100 * ヘッダー部のカレンダに、calDB で指定された カレンダテーブルを使用出来ます。
101 * 使用する場合は、arg1(事業所コード等)〜arg4(WCコード等) の属性を指定する事ができます。
102 * zoom="10"(週単位) を使用の週数の計算は、年初の最初の7日間が含まれる週を、第1週と数えます。
103 *
104 * zoom="20"(時)間 では、1日の時間範囲をdaySpanでHHmm-HHmm形式で指定します。
105 * 開始時刻は、内部で1時間単位に変換されます。8時30分〜は、8時〜になります。
106 * 終了時間は、その時間を「含みません」
107 * 開始終了は、startDate、endDateで指定しますが、yyyyMMdd または、yyyyMMddHHmm 形式とします。
108 * calDB で指定された カレンダテーブルを見て、休日の場合は、表示をスキップします。
109 * 休憩時間は、breakTimes で指定します。(HHmm-HHmm形式、または、yyyyMMddHHmm-HHmm、
110 * または、yyyyMMddHHmm-yyyyMMddHHmm形式)
111 * カンマ区切りで複数指定できます。日付指定がない場合は、毎日、日付指定がある場合は、
112 * その日のみ有効です。休憩時間は、日をまたぐ事は可能です。
113 * breakTimeStyle として、休憩時間の指定に追加するスタイル属性を追加します。
114 * 通常は、バックカラーと上からの位置です。ヘッダー表示は、1時間単位です。
115 * 初期値は、"top:20px;background-color:yellow;filter:alpha(opacity=60);opacity:0.60;" です。
116 *
117 * ベース時刻(baseTimes)は、HHmm形式、または、yyyyMMddHHmm形式で指定した箇所に、線を引きます。
118 * 例えば、検索した時刻を指定すると、現在時刻の箇所を示す線になります。
119 * また、業務自体の開始時刻や終了時刻の箇所を表すことも可能です。
120 * baseTimeStyle は、このベース時刻のスタイルを決めます。breakTimeStyle との違いは、
121 * 帯の幅を、このスタイルシートで指定していることです。
122 * 初期値は、top:20px;background-color:transparent;border-left:2px dashed red; です。
123 *
124 * zoom="21"(時)間 では、一時間のピクセルを"20"(時)の半分に変更します。
125 *
126 * useMultiClm  パラメータを設定すると、ガントヘッダーにおいて、2段組を使用するかどうかを、
127 * 指定できます。時間ヘッダーの上段に日付を、下段の時間軸の(h)の削除を行います。
128 * 日付は、表示開始時刻の上と、それの6時間ごとに表示します。
129 * 初期値は、システムリソースの USE_GANTTHEADER_MULTIPLE_COLUMN で指定します。
130 *
131 * システムリソースに USE_GANTTHEADER_MONTH_DATE パラメータを設定すると、
132 * ガントヘッダーにおいて、30日、90日、180日のヘッダー表示で、日付まで
133 * 表示するか、月のみ表示するかを指定します。
134 * ガントヘッダーの繰返し表示でバックグラウンドイメージは固定日なので、一月表示を
135 * 30日単位で表示していますが、先頭日付が 1日でないため、判りにくいと苦情がありました。
136 * そこで、30日、90日、180日のヘッダー表示時に、日付を表示しないようにするフラグです。
137 * 月表示は、その月が 20日以降の場合、翌月を表示します。
138 * 初期値は、互換性の為、false です。
139 *
140 * zoom 40(DAY),41(WEEK),42(MONTH) は、積み上げガント用のヘッダー処理を行います。
141 * 積み上げガントは、固定日処理ではなく、月単位に加算します。
142 *
143 * @og.rev 3.5.4.8 (2004/02/23) 新規作成
144 * @og.group 画面部品
145 *
146 * @version  4.0
147 * @author      Kazuhiko Hasegawa
148 * @since    JDK5.0,
149 */
150public class GanttHeaderTag extends CommonTagSupport {
151        //* このプログラムのVERSION文字列を設定します。   {@value} */
152        private static final String VERSION = "5.7.6.2 (2014/05/16)" ;
153
154        private static final long serialVersionUID = 576220140516L ;
155
156        // 5.6.2.3 (2013/03/22) 日付をセンターに表示させる場合の両端スペースの元ネタ
157        private static final String SPACE = "                                   " ;             // 日付(31日分)より多いスペース
158
159        // 5.6.5.0 (2013/06/07) 曜日データを配列で持っておきます。
160        private static final String[] DAY_OF_WEEK_ja = new String[] { " ","日 ","月 ","火 ","水 ","木 ","金 ","土 " };
161        private static final String[] DAY_OF_WEEK_en = new String[] { " ","Su" ,"Mo" ,"Tu" ,"We" ,"Th" ,"Fr" ,"Sa"  };
162
163        private String  startDate       = null;
164        private String  endDate         = null;
165        private String  daySpan         = "0700-2000";  // 1日の時間範囲(HHmm-HHmm) 3.8.0.5 (2005/08/26)
166        private int             zoom            = 2;
167        private String  breakTimes      = null;         // 休憩時間は、HHmm-HHmm形式、または、yyyyMMddHHmm-HHmm、または、yyyyMMddHHmm-HHmmyyyyMMdd形式です。
168        private String  breakTimeStyle  = "top:20px;background-color:yellow;filter:alpha(opacity=60);opacity:0.60;" ;   // 5.6.4.3 (2013/05/24) 初期値変更
169        private String  calDB   = null; // 3.6.0.0 (2004/09/17) DB検索するDBのキー
170        private String  arg1    = null; // 3.6.0.0 (2004/09/17) DB検索の第1キー(事業所コードなど)
171        private String  arg2    = null; // 3.6.0.0 (2004/09/17) DB検索の第2キー(WCコードなど)
172        private String  arg3    = null; // 3.6.0.0 (2004/09/17) DB検索の第3キー(事業所コードなど)
173        private String  arg4    = null; // 3.6.0.0 (2004/09/17) DB検索の第4キー(WCコードなど)
174        private boolean skipHoliday     = HybsSystem.sysBool( "USE_GANTTHEADER_SKIP_HOLIDAY" );         // 4.0.0.0 (2007/09/07) 休日をスキップするかどうか
175        private String  calStr  = null; // 5.5.4.0 (2012/07/02) 出勤日・休日のフラグ
176
177        private static final int         TIME_PIXEL             = 48;   // 3.8.1.1 (2005/11/21) 時間ヘッダー時の1時間のピクセル数
178//      private static final boolean USE_MULTI_CLM      = HybsSystem.sysBool( "USE_GANTTHEADER_MULTIPLE_COLUMN" );      // 3.8.1.4 (2006/03/13)
179        private boolean useMultiClm     = HybsSystem.sysBool( "USE_GANTTHEADER_MULTIPLE_COLUMN" );      // 5.6.1.2 (2013/02/22)
180
181        private static final boolean USE_MONTH_DATE     = HybsSystem.sysBool( "USE_GANTTHEADER_MONTH_DATE" );   // 3.8.5.2 (2006/06/09)
182        private static final int         MONTH_DATE_LIMITER = 20;       // 当月 20 日以降は、翌月扱いとなる。
183
184        private static final String BLUE_COLOR  = "<span style=\"color:Blue;\">" ;                // 5.6.2.3 (2013/03/22) 廃止
185        private static final String RED_COLOR   = "<span style=\"color:Red;\">" ;         // 5.6.2.3 (2013/03/22) 廃止
186        private static final String TODAY_CLASS         = "gntToday" ;                                          // 5.6.2.3 (2013/03/22) 当日を示すクラス名
187        private static final String HOLIDAY_CLASS       = "gntHoliday" ;                                        // 5.6.2.3 (2013/03/22) 休日を示すクラス名
188        private static final String END_SPAN    = "</span>" ;
189        private static final String BR                  = "<br/>" ;
190
191        private static final String ODD_CLASS   = "<span class=\"oddColor\">" ;                   // 5.6.2.3 (2013/03/22) 奇数月の色設定
192        private static final String EVEN_CLASS  = "<span class=\"evenColor\">" ;          // 5.6.2.3 (2013/03/22) 偶数月の色設定
193
194        private String  baseTimes               = null;                                                                         // 5.6.1.2 (2013/02/22) ベース時刻は、HHmm形式、または、yyyyMMddHHmm形式です。
195        private String  baseTimeStyle   = "top:20px;background-color:transparent;border-left:2px dashed red;" ;         // 5.6.1.2 (2013/02/22) ベース時刻を赤線表示します。
196        
197        private static final boolean useMdheader        = HybsSystem.sysBool( "USE_MDHEADER_ONTIME" ); // 5.7.0.0 (2013/11/07)
198
199        /**
200         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
201         *
202         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
203         * @og.rev 3.6.0.0 (2004/09/17) zoom 3 の時の計算値を変更
204         * @og.rev 3.7.1.0 (2005/04/15) zoom 10 の追加
205         * @og.rev 3.8.1.6 (2006/04/25) zoom 21 の追加
206         * @og.rev 3.8.5.2 (2006/06/09) makeZoom メソッドの USE_MONTH_DATE パラメータ追加
207         * @og.rev 3.8.9.2 (2007/07/28) makeZoomTime メソッドの 時間間隔パラメータ追加
208         * @og.rev 5.5.4.0 (2012/07/02) ヘッダー属性情報の出力追加
209         * @og.rev 5.6.3.2 (2013/04/12) 曜日を出力する場合の段組みでは、全角スペースを使う(firefox対応)
210         *
211         * @return      後続処理の指示
212         */
213        @Override
214        public int doEndTag() {
215                debugPrint();           // 4.0.0 (2005/02/28)
216                if( startDate == null || endDate == null ||
217                         startDate.length() < 8 || endDate.length() < 8 ) {
218                                String errMsg = "開始日と終了日は、どちらも yyyyMMdd 形式で、必須です。"
219                                                + " startDate=[" + startDate + "] endDate=[" + endDate + "]" ;
220                                throw new HybsSystemException( errMsg );
221                }
222
223                // 月単位の処理に30,60,90などの固定日を使用しているのは、ガントバーの長さが
224                // 日単位の固定長なので、長期間のガントを使用すると後ろの方でずれてくるため。
225                String header = "";
226                String md = (USE_MONTH_DATE) ? "MM   " : "MM/dd";
227                switch( zoom ) {
228                        case  0: header = makeZoom( "MM/   "     ,"dd(EE)"     ,  1 ,false ) ; break;
229                        case  1: header = makeZoom( "MM/"        ,"dd "        ,  1 ,false ) ; break;
230                        case  2: header = makeZoom2( 1 ) ; break;
231                        case  3: header = makeZoom( "yyyy/  "    ,"MM/dd  "    ,  7 ,false ) ; break;
232                        case  4: header = makeZoom( "yyyy/  "    ,"MM/dd  "    , 14 ,false ) ; break;
233                        case  5: header = makeZoom( "yyyy/     " ,md + "     " , 30 ,USE_MONTH_DATE ) ; break;
234                        case  6: header = makeZoom( "yyyy/ "     ,md + " "     , 30 ,USE_MONTH_DATE ) ; break;
235                        case  7: header = makeZoom( "yyyy/     " ,md + "     " , 90 ,USE_MONTH_DATE ) ; break;
236                        case  8: header = makeZoom( "yyyy/     " ,md + "     " ,180 ,USE_MONTH_DATE ) ; break;
237                        case  9: header = makeZoom( "yyyy/ "     ,md + " "     ,180 ,USE_MONTH_DATE ) ; break;
238                        case 10: header = makeZoom( "ww'W'"      ,"'<span title=\"'MM/dd'\">'dd '</span>'" ,7 ,false ) ; break;
239        //              case 11: break; // 他物件予約済み
240        //              case 12: break; // 他物件予約済み
241                        case 13: header = makeZoom3( "yyyy/MM" , "dd"  ,"EE"  ,  1 ) ; break;           // 5.6.2.3 (2013/03/22) 月、曜日表示
242                        case 20: header = makeZoomTime( TIME_PIXEL  ,  1,true  ) ; break;       // 3.8.1.1 (2005/11/21)
243                        case 21: header = makeZoomTime( TIME_PIXEL/2,  1,false ) ; break;       // 3.8.1.6 (2006/04/25)
244                        case 22: header = makeZoomTime( TIME_PIXEL  ,  2,true  ) ; break;       // 3.8.9.2 (2007/07/28)
245                        case 23: header = makeZoomTime( TIME_PIXEL/2,  2,false ) ; break;       // 3.8.9.2 (2007/07/28)
246                        case 24: header = makeZoomTime( TIME_PIXEL  ,  4,true  ) ; break;       // 3.8.9.2 (2007/07/28)
247                        case 25: header = makeZoomTime( TIME_PIXEL/2,  4,false ) ; break;       // 3.8.9.2 (2007/07/28)
248                        case 26: header = makeZoomTime( TIME_PIXEL  ,  6,true  ) ; break;       // 3.8.9.2 (2007/07/28)
249                        case 27: header = makeZoomTime( TIME_PIXEL/2,  6,false ) ; break;       // 3.8.9.2 (2007/07/28)
250                        case 28: header = makeZoomTime( TIME_PIXEL  ,  8,true  ) ; break;       // 3.8.9.2 (2007/07/28)
251                        case 29: header = makeZoomTime( TIME_PIXEL/2,  8,false ) ; break;       // 3.8.9.2 (2007/07/28)
252                        case 30: header = makeZoomTime( TIME_PIXEL  , 12,true  ) ; break;       // 3.8.9.2 (2007/07/28)
253                        case 31: header = makeZoomTime( TIME_PIXEL/2, 12,false ) ; break;       // 3.8.9.2 (2007/07/28)
254                        // 5.6.1.2 (2013/02/22) 積み上げガント
255                        case 40: header = makeZoomStack( "MM/   "     ,"dd(EE)"     ,  1,false ) ; break;       // 5.6.1.2 (2013/02/22)
256                        case 41: header = makeZoomStack( "ww'W'   "   ,"MM/dd "     ,  7,false ) ; break;       // 5.6.1.2 (2013/02/22)
257                        case 42: header = makeZoomStack( "yyyy/     " ,"MM        " ,  1,true  ) ; break;       // 5.6.1.2 (2013/02/22)
258        //              case 43: break;         // 日単位ヘッダー予約済み
259        //                       〜
260        //              case 49: break;         // 日単位ヘッダー予約済み
261                        default: break;
262                }
263
264                jspPrint( header );
265                jspPrint(makeHeaderData()); // 5.5.4.0 (2012/07/02)
266                return(EVAL_PAGE);
267        }
268
269        /**
270         * タグリブオブジェクトをリリースします。
271         *
272         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
273         *
274         * @og.rev 3.6.0.0 (2004/09/17) 事業所コード cdjgs 属性を追加
275         * @og.rev 3.8.0.2 (2005/07/11) startTime,timePeriod,breakTimes 属性を追加
276         * @og.rev 3.8.0.5 (2005/08/26) daySpan,breakTimes,breakTimeStyle 属性を追加
277         * @og.rev 5.5.4.0 (2012/07/02) calStr追加
278         * @og.rev 5.6.1.2 (2013/02/22) baseTimes、baseTimeStyle追加,useMultiClm追加
279         */
280        @Override
281        protected void release2() {
282                super.release2();
283                startDate       = null;
284                endDate         = null;
285                daySpan         = "0700-2000";  // 開始時刻(HHmm-HHmm) 3.8.0.5 (2005/08/26)
286                zoom            = 2;
287                calDB           = null; // 3.6.0.0 (2004/09/17) DB検索するDBのキー
288                arg1            = null; // 3.6.0.0 (2004/09/17) DB検索の第1キー(事業所コードなど)
289                arg2            = null; // 3.6.0.0 (2004/09/17) DB検索の第2キー(WCコードなど)
290                arg3            = null; // 3.6.0.0 (2004/09/17) DB検索の第3キー
291                arg4            = null; // 3.6.0.0 (2004/09/17) DB検索の第4キー
292                breakTimes      = null;         // 休憩時間は、HHmm-HHmm形式、または、yyyyMMddHHmm-HHmm、または、yyyyMMddHHmm-HHmmyyyyMMdd形式です。
293                breakTimeStyle  = "top:20px;background-color:yellow;filter:alpha(opacity=60);opacity:0.60;" ;
294                skipHoliday = HybsSystem.sysBool( "USE_GANTTHEADER_SKIP_HOLIDAY" ); // 4.0.0.0 (2007/09/10)
295                calStr          = null; // 5.5.4.0 (2012/07/02)
296                baseTimes               = null;                                                                         // 5.6.1.2 (2013/02/22) ベース時刻は、HHmm形式、または、yyyyMMddHHmm形式です。
297                baseTimeStyle   = "top:20px;background-color:transparent;border-left:2px dashed red;" ;         // 5.6.1.2 (2013/02/22) ベース時刻を赤線表示します。
298                useMultiClm             = HybsSystem.sysBool( "USE_GANTTHEADER_MULTIPLE_COLUMN" );      // 5.6.1.2 (2013/02/22)
299        }
300
301        /**
302         * 上段・下段のフォーマットと、加算日に応じたヘッダー文字列を作成します。
303         *
304         * @og.rev 3.6.0.0 (2004/09/17) 休日判断を、事業所カレンダを使用
305         * @og.rev 3.7.1.0 (2005/04/15) zoom == 10 週単位の場合の特殊処理を追加
306         * @og.rev 3.7.1.1 (2005/05/23) 本日は、青色で示します。
307         * @og.rev 3.8.5.2 (2006/06/09) makeZoom メソッドの USE_MONTH_DATE パラメータ追加
308         * @og.rev 5.5.4.0 (2012/07/02) カレンダーフラグ対応
309         * @og.rev 5.6.2.3 (2013/03/22) 日付の終了日は、「含む」に変更
310         * @og.rev 5.6.5.0 (2013/06/07) 上段ヘッダーが MM の場合、週単位で月を表示し、色バーを使用します。
311         * @og.rev 5.7.2.0 (2014/01/10) 上段は、休日を出さないので、END_SPAN 不要
312         *
313         * @param       upper   上段の表示フォーマット
314         * @param       lower   下段の表示フォーマット
315         * @param       add     表示日付けの加算
316         * @param       useMonth        月日表示でなく、月表示のみにする。(20日以降を翌月表示する。)
317         *
318         * @return  ヘッダー文字列
319         */
320        private String makeZoom( final String upper ,final String lower ,final int add, final boolean useMonth ) {
321                boolean colBar = upper.startsWith( "MM" );              // 5.6.5.0 (2013/06/07) 色バー使用 true
322
323                DateFormat format1 = new SimpleDateFormat( upper,Locale.JAPAN );
324                DateFormat format2 = new SimpleDateFormat( lower,Locale.JAPAN );
325
326                Calendar str = HybsSystem.getCalendar( startDate );
327                Calendar end = HybsSystem.getCalendar( endDate );
328
329                // zoom == 10 週単位の場合の特殊処理。
330                // 年の第一週を完全な一週間分(7日間)として、設定します。
331                if( zoom == 10 ) {
332                        str.setMinimalDaysInFirstWeek( 7 );
333                        format1.setCalendar( str );
334                        format2.setCalendar( str );
335                }
336
337                StringBuilder buf1   = new StringBuilder( HybsSystem.BUFFER_SMALL );
338                StringBuilder buf2   = new StringBuilder( HybsSystem.BUFFER_SMALL );
339                StringBuilder bufcal = new StringBuilder( HybsSystem.BUFFER_SMALL ); // 5.5.4.0 (2012/07/02) 休日判定用
340
341                // 5.6.5.0 (2013/06/07) 文字列の作成方法の統一。pre タグを最初に設定しておく。
342                buf1.append( "<pre>" );
343
344                // 3.6.0.0 (2004/09/17) カレンダDB検索機能を追加
345                CalendarData calData = CalendarFactory.getCalendarData( calDB,arg1,arg2,arg3,arg4 );
346
347                boolean modifyFlag = false;
348                // 5.6.2.3 (2013/03/22) 日付の終了日は、「含む」に変更
349//              while( str.before( end ) ) {
350                int cnt  = 0;                                                                   // 5.6.5.0 (2013/06/07) 色バー対応
351                if( colBar ) { buf1.append( EVEN_CLASS ); }             // 5.6.5.0 (2013/06/07) 色バー対応
352                boolean isFirst = true;                                                 // 5.6.5.0 (2013/06/07) 色バー対応で、最初だけ、月を表示する。
353
354                while( str.compareTo( end ) <= 0 ) {
355                        boolean monday = ( Calendar.MONDAY == str.get( Calendar.DAY_OF_WEEK ) );        // 5.6.5.0 (2013/06/07) 色バー対応
356                        if( colBar && monday ) {
357                                // 5.6.5.0 (2013/06/07) 色バー対応
358                                buf1.append( END_SPAN );
359                                cnt++;
360                                isFirst = true;
361
362                                if( cnt % 2 == 0 )      { buf1.append( EVEN_CLASS ); }          // 偶数の色
363                                else                            { buf1.append( ODD_CLASS  ); }          // 奇数の色
364                        }
365
366                        Date dt = str.getTime();
367                        // 3.8.5.2 (2006/06/09) useMonth フラグにより 月表示のみに変更します。
368                        // MONTH_DATE_LIMITER で指定の日以降は、翌月扱いとなる。
369                        if( useMonth && str.get( Calendar.DATE ) >= MONTH_DATE_LIMITER ) {
370                                Calendar calPlus = (Calendar)str.clone();
371                                calPlus.set( Calendar.DATE , 1 );               // 1日にセットします。
372                                calPlus.add( Calendar.MONTH , 1 );              // 月を1ヶ月プラスします。
373                                dt = calPlus.getTime();
374                        }
375
376                        // 3.7.1.1 (2005/05/31) 本日は、青色で示します。
377                        if( calData.isContainedToday( str,add ) ) {
378//                              buf1.append( BLUE_COLOR );
379                                buf2.append( BLUE_COLOR );
380                                bufcal.append( "0" ); // 5.5.4.0 (2012/07/02)
381                                modifyFlag = true;
382                        }
383
384                        // 3.6.0.0 (2004/09/17) 休日判断を、事業所カレンダを使用
385                        // modifyFlag が立っていない場合 を条件に追加します。
386                        if( !modifyFlag && add == 1 && calData.isHoliday( str ) ) {
387//                              buf1.append( RED_COLOR );
388                                buf2.append( RED_COLOR );
389                                bufcal.append( "1" ); // 5.5.4.0 (2012/07/02) 休日
390                                modifyFlag = true;
391                        }
392
393                        // 5.6.5.0 (2013/06/07) 色バー対応。色バーで、かつ、先頭でなければ、スペースを出力
394                        if( colBar && !isFirst ) {
395                                buf1.append( SPACE.substring( 0,upper.length() ) );
396                        }
397                        else {
398                                buf1.append( format1.format( dt ) );
399                                isFirst = false;
400                        }
401                        buf2.append( format2.format( dt ) );
402
403                        if( modifyFlag ) {
404//                              buf1.append( END_SPAN );                // 5.7.2.0 (2014/01/10) 上段は、休日を出さないので、END_SPAN 不要
405                                buf2.append( END_SPAN );
406                                modifyFlag = false;
407                        }
408                        else{
409                                bufcal.append( "0" ); // 5.5.4.0 (2012/07/02)
410                        }
411                        str.add(Calendar.DATE, add);
412                }
413                calStr = bufcal.toString(); // 5.5.4.0 (2012/07/02)
414
415                if( colBar ) { buf1.append( END_SPAN ); }               // 5.6.5.0 (2013/06/07) 色バー対応
416
417//              return "<pre>" + buf1.toString() + BR + buf2.toString() + "</pre>";
418                return buf1.append( BR ).append( buf2 ).append( "</pre>" ).toString();            // 5.6.5.0 (2013/06/07) 文字列の作成方法の統一
419        }
420
421        /**
422         * zoom = 2 の場合のヘッダーを出力します。
423         * このヘッダーだけ特別なので、別メソッドを作成します。
424         *
425         * type=1 の場合
426         * [ 0   ・・・]&lt;br/&gt;[ 2   ・・・]&lt;br/&gt;[ /   ・・・]&lt;br/&gt;[0000 ・・・]&lt;br/&gt;[1234 ・・・]
427         *
428         * という月情報を毎週月曜日にヘッダーに出力します。(上記は、2月1日〜2月4日まで)
429         *
430         * @og.rev 3.6.0.0 (2004/09/17) 休日判断を、事業所カレンダを使用
431         * @og.rev 3.6.0.7 (2004/11/06) 月の情報も出力します。
432         * @og.rev 3.7.1.1 (2005/05/23) 本日は、青色で示します。
433         * @og.rev 5.5.4.0 (2012/07/02) カレンダーフラグ対応
434         * @og.rev 5.6.2.3 (2013/03/22) 日付の終了日は、「含む」に変更
435         * @og.rev 5.6.5.0 (2013/06/07) 日付欄の段組みを廃止し、色バーに変更します。
436         *
437         * @param       add     表示日付けの加算
438         *
439         * @return  ヘッダー文字列
440         */
441        private String makeZoom2( final int add ) {
442                Calendar str = HybsSystem.getCalendar( startDate );
443                Calendar end = HybsSystem.getCalendar( endDate );
444
445                StringBuilder buf1   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 月の1桁目
446//              StringBuilder buf2   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 月の2桁目        5.6.5.0 (2013/06/07) 色バーに変更
447//              StringBuilder buf3   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 区切り記号        5.6.5.0 (2013/06/07) 色バーに変更
448                StringBuilder buf4   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 日の1桁目
449                StringBuilder buf5   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 日の2桁目
450                StringBuilder bufcal = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 5.5.4.0 (2012/07/02) 休日判定用
451
452                // 5.6.5.0 (2013/06/07) 文字列の作成方法の統一。pre タグを最初に設定しておく。
453                buf1.append( "<pre>" );
454
455                // 3.6.0.0 (2004/09/17) カレンダDB検索機能を追加
456                CalendarData calData = CalendarFactory.getCalendarData( calDB,arg1,arg2,arg3,arg4 );
457
458                boolean modifyFlag = false;
459
460                // 5.6.2.3 (2013/03/22) 日付の終了日は、「含む」に変更
461//              while( str.before( end ) ) {
462                int cnt  = 0;                                   // 5.6.5.0 (2013/06/07) 色バー対応
463                int hCnt = 0;                                   // 月欄は、3文字分
464                buf1.append( EVEN_CLASS );              // 5.6.5.0 (2013/06/07) 色バー対応
465                while( str.compareTo( end ) <= 0 ) {
466                        int mt = str.get( Calendar.MONTH ) + 1;
467                        int dt = str.get( Calendar.DATE );
468                        boolean monday = ( Calendar.MONDAY == str.get( Calendar.DAY_OF_WEEK ) );
469
470                        // 3.7.1.1 (2005/05/31) 本日は、青色で示します。
471                        if( calData.isContainedToday( str,add ) ) {
472//                              buf1.append( BLUE_COLOR );
473//                              buf2.append( BLUE_COLOR );
474//                              buf3.append( BLUE_COLOR );
475                                buf4.append( BLUE_COLOR );
476                                buf5.append( BLUE_COLOR );
477                                bufcal.append("0"); // 5.5.4.0 (2012/07/02)
478                                modifyFlag = true;
479                        }
480
481                        // 3.6.0.0 (2004/09/17) 休日判断を、事業所カレンダを使用
482                        // modifyFlag が立っていない場合 を条件に追加します。
483                        if( !modifyFlag && add == 1 && calData.isHoliday( str ) ) {
484//                              buf1.append( RED_COLOR );
485//                              buf2.append( RED_COLOR );
486//                              buf3.append( RED_COLOR );
487                                buf4.append( RED_COLOR );
488                                buf5.append( RED_COLOR );
489                                bufcal.append("1"); // 5.5.4.0 (2012/07/02)
490                                modifyFlag = true;
491                        }
492
493                        if( monday ) {
494                                // 5.6.5.0 (2013/06/07) 色バー対応
495                                buf1.append( END_SPAN );
496                                cnt++;
497                                hCnt = 0;
498
499                                if( cnt % 2 == 0 )      { buf1.append( EVEN_CLASS ); }          // 偶数の色
500                                else                            { buf1.append( ODD_CLASS  ); }          // 奇数の色
501
502//                              buf1.append( (mt/10) );
503//                              buf2.append( mt%10 );
504//                              buf3.append( "/" );
505                        }
506//                      else {
507//                              buf1.append( " " );
508//                              buf2.append( " " );
509//                              buf3.append( " " );
510//                      }
511
512                        // 5.6.5.0 (2013/06/07) 色バー対応
513                        switch( hCnt++ ) {
514                                case 0 :        buf1.append( (mt/10) ); break;          // 月の1文字目
515                                case 1 :        buf1.append(  mt%10  ); break;          // 月の2文字目
516                                case 2 :        buf1.append(   "/"   ); break;          // 月の区切り文字
517                                default :       buf1.append(   " "   ); break;          // 空欄
518                        }
519
520                        buf4.append( (dt/10) );
521                        buf5.append( dt%10 );
522
523                        if( modifyFlag ) {
524//                              buf1.append( END_SPAN );
525//                              buf2.append( END_SPAN );
526//                              buf3.append( END_SPAN );
527                                buf4.append( END_SPAN );
528                                buf5.append( END_SPAN );
529                                modifyFlag = false;
530                        }
531                        else{
532                                bufcal.append("0"); // 5.5.4.0 (2012/07/02)
533                        }
534                        str.add(Calendar.DATE, add);
535                }
536
537//              buf1.append( BR ).append( buf2 );
538//              buf1.append( BR ).append( buf3 );
539                buf1.append( END_SPAN );                                // 5.6.5.0 (2013/06/07) 色バー対応
540//              buf1.append( BR ).append( buf4 );
541//              buf1.append( BR ).append( buf5 );
542                calStr = bufcal.toString();                             // 5.5.4.0 (2012/07/02)
543
544//              return "<pre>" + buf1.toString() + "</pre>";
545                return buf1.append( BR ).append( buf4 ).append( BR ).append( buf5 ).append( "</pre>" ).toString();                // 5.6.5.0 (2013/06/07) 文字列の作成方法の統一
546        }
547
548        /**
549         * ヘッダー、上段・下段のフォーマットと、加算日に応じたヘッダー文字列を作成します。
550         * これは特殊で、ヘッダーに、年/月、上段は日、下段は、曜日を想定しています。
551         * ヘッダー部分は、月として横持で表示させます。
552         *
553         * @og.rev 5.6.2.3 (2013/03/22) 新規追加
554         *
555         * @param       header  年月のヘッダー部分
556         * @param       upper   上段の表示フォーマット(日)
557         * @param       lower   下段の表示フォーマット(曜日)
558         * @param       add     表示日付けの加算
559         *
560         * @return  ヘッダー文字列
561         */
562        private String makeZoom3( final String header ,final String upper ,final String lower ,final int add ) {
563                DateFormat formatH = new SimpleDateFormat( header,Locale.JAPAN );
564                DateFormat format1 = new SimpleDateFormat( upper,Locale.JAPAN );
565                DateFormat format2 = new SimpleDateFormat( lower,Locale.JAPAN );
566
567                StringBuilder bufH   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 年月のヘッダー部分(11Byte目から)
568                StringBuilder buf1   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 日(2桁)
569                StringBuilder buf2   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 曜日
570                StringBuilder bufcal = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 5.5.4.0 (2012/07/02) 休日判定用
571
572                // 5.6.5.0 (2013/06/07) 文字列の作成方法の統一。pre タグを最初に設定しておく。
573                bufH.append( "<pre>" );
574
575                Calendar str = HybsSystem.getCalendar( startDate );
576                Calendar end = HybsSystem.getCalendar( endDate );
577
578                // 3.6.0.0 (2004/09/17) カレンダDB検索機能を追加
579                CalendarData calData = CalendarFactory.getCalendarData( calDB,arg1,arg2,arg3,arg4 );
580
581                int     dtsu            = lower.length();                                               // 日付欄(下段)の文字数
582                int     dayCount        = 0;                                                                    // ヘッダー部の文字が入るかどうかの基準
583                int     mtCnt           = str.get( Calendar.MONTH ) + 1;                // 月をチェック(色設定用) 初期値は、開始時の月
584                String tmpH             = null;                                                                 // ヘッダー部のテンポラリ情報
585                // 5.6.2.3 (2013/03/22) 日付の終了日は、「含む」に変更
586//              while( str.before( end ) ) {
587                while( str.compareTo( end ) <= 0 ) {
588                        Date dt = str.getTime();
589
590                        if( tmpH == null ) { tmpH = formatH.format( dt ); }     // 初期値。最初にセット
591
592                        // ここから一連の処理は、月表示ヘッダーの作成
593                        int day = str.get( Calendar.DATE );                     // ヘッダー部の制御用に、日付が必要
594                        if( day == 1 && dayCount > 0 ) {
595                                makeHeaderYM( bufH , dayCount*dtsu , mtCnt++ , tmpH );          // このヘッダー出力は、ひと月前の情報
596                                dayCount = 0 ;
597                                tmpH     = formatH.format( dt );
598                        }
599                        dayCount ++ ;   // 
600
601                        // 5.6.2.3 (2013/03/22) 休日、本日の処理を class属性化で、合成可能とします。
602                        String span = null;
603                        // 3.6.0.0 (2004/09/17) 休日判断を、事業所カレンダを使用
604                        if( calData.isHoliday( str ) ) {
605                                span = HOLIDAY_CLASS ;
606                                bufcal.append( "1" ); // 5.5.4.0 (2012/07/02) 休日
607                        }
608                        else {
609                                bufcal.append( "0" ); // 5.5.4.0 (2012/07/02)
610                        }
611
612                        if( calData.isContainedToday( str,add ) ) {                             // 本日かどうか
613                                span = (span == null) ? TODAY_CLASS : span + " " + TODAY_CLASS ;
614                        }
615
616                        if( span != null ) {
617                                buf1.append( "<span class=\"" ).append( span ).append( "\">" );
618                                buf2.append( "<span class=\"" ).append( span ).append( "\">" );
619                        }
620
621                        buf1.append( format1.format( dt ) );
622                        buf2.append( format2.format( dt ) );
623
624                        if( span != null ) {
625                                buf1.append( END_SPAN );
626                                buf2.append( END_SPAN );
627                        }
628                        str.add(Calendar.DATE, add);
629                }
630
631                // 処理の最後に、ヘッダーの出力は必要
632                makeHeaderYM( bufH , dayCount*dtsu , mtCnt , tmpH );
633
634                calStr = bufcal.toString(); // 5.5.4.0 (2012/07/02)
635
636//              return "<pre>" + bufH.toString() + BR + buf1.toString() + BR + buf2.toString() + "</pre>";
637                return bufH.append( BR ).append( buf1 ).append( BR ).append( buf2 ).append( "</pre>" ).toString();                // 5.6.5.0 (2013/06/07) 文字列の作成方法の統一
638        }
639
640        /**
641         * 時間軸での月ヘッダーデータを作成します。
642         *
643         * 月ヘッダーは、1日〜月末までの日付の上段に、年月(yyyy/MM)表示のヘッダーを作成します。
644         * ヘッダーは、できるだけセンター表示になるように、前後にスペースを入れて調整します。
645         * ヘッダー表示領域が少ない場合、スペースのみになります。
646         * ヘッダーは月が偶数月か奇数月かで、背景色を切り替えることで、判りやすくします。
647         *
648         * @og.rev 5.6.2.3 (2013/03/22) 新規追加
649         *
650         * @param               bufH    ヘッダーを追記していく StringBuilder
651         * @param               dayCnt  日付欄の文字数カウント。日数*桁数(DTSU)。通常、横持なら 2桁 となる。
652         * @param               mtCnt   月数に基づいた色の設定用の数字。月の連番にします。
653         * @param               ymStr   ヘッダーに表示する文字列。年月(yyyy/MM)
654         *
655         * @return  ヘッダーが追記された StringBuilder
656         */
657        private StringBuilder makeHeaderYM( final StringBuilder bufH , final int dayCnt , final int mtCnt , final String ymStr ) {
658                // 奇数月と偶数月で色を変える。将来的に % 3 で判定すれば、3色で廻せる。
659                if( mtCnt % 2 == 0 )    { bufH.append( EVEN_CLASS ); }          // 偶数月の色
660                else                                    { bufH.append( ODD_CLASS  ); }          // 奇数月の色
661
662                // 表示すべき文字列が、日付欄の幅よりも小さい場合、スペースのみとする。
663                if( dayCnt < ymStr.length() ) {
664                        bufH.append( SPACE.substring( 0,dayCnt ) );
665                }
666                // 大きい場合は、前後にスペースを入れて、センター配置
667                else {
668                        int lcnt = (dayCnt-ymStr.length())/2 ;          // 左の個数。端数が切り捨てられる。
669                        int rcnt = dayCnt-lcnt-ymStr.length();          // 右の個数。端数を考慮し、引き算のみで求める。
670
671                        bufH.append( SPACE.substring( 0,lcnt ) );
672                        bufH.append( ymStr );
673                        bufH.append( SPACE.substring( 0,rcnt ) );
674                }
675
676                bufH.append( END_SPAN );
677
678                return bufH;
679        }
680
681        /**
682         * 時間軸でのヘッダー表示を行います。
683         *
684         * 時間軸の為、ヘッダーの上下段組は行いません。
685         * ヘッダーは、1時間単位に表示します。また、休憩時刻も求めています。
686         *
687         * @og.rev 3.8.0.5 (2005/08/26) 新規追加
688         * @og.rev 3.8.1.1 (2005/11/21) 日付title,範囲class,
689         * @og.rev 3.8.1.4 (2006/03/13) 日付表示、時刻単位(h)削除、2段組(USE_MULTI_CLM)
690         * @og.rev 3.8.1.6 (2006/04/25) 日や時間の単位表示を止め、2文字分(24ピクセル)化する。
691         * @og.rev 3.8.9.2 (2007/07/28) 時間間隔パラメータ追加
692         * @og.rev 4.0.0.0 (2007/09/03) 休日の場合でも表示されるように対応(システムリソースで切り替え)
693         * @og.rev 5.5.4.0 (2012/07/02) ガントの一日表示枠の計算を切り上げするようにする。カレンダーフラグ対応。
694         * @og.rev 5.6.1.2 (2013/02/22) ベース時刻を管理。 ym2int 廃止 ⇒ hm2int に変更。 USE_MULTI_CLM ⇒ useMultiClm 変更。
695         * @og.rev 5.6.4.3 (2013/05/24) ヘッダーずれ対応。"日" を2文字の、"日 " に修正。
696         * @og.rev 5.6.5.0 (2013/06/07) 色バーに変更します。
697         * @og.rev 5.6.7.0 (2013/11/03) 時間軸の上段ヘッダーに月日を表示
698         *
699         * @param               hourOfPixcel 1時間あたりのピクセル数。
700         * @param               step  時間間隔の指定(1:1時間間隔、2:2時間間隔・・・・)
701         * @param               useTani  日や時間の単位表示を行う(true)か、行わない(false)か
702         *
703         * @return  ヘッダー文字列
704         */
705//      private String makeZoomTime( final int hourOfPixcel,final boolean useTani ) {
706        private String makeZoomTime( final int hourOfPixcel,final int step,final boolean useTani ) {
707//              DateFormat format1 = new SimpleDateFormat( "yyyy/MM/dd",Locale.JAPAN );
708                DateFormat format1 = new SimpleDateFormat( "yyyy/MM/dd(EE)",Locale.JAPAN );             // 5.6.5.0 (2013/06/07) 曜日を、tipsに出す。
709                DateFormat format2 = new SimpleDateFormat( "MM/dd",Locale.JAPAN );                              // 5.7.0.0 (2013/11/03) 上段
710
711                StringBuilder bufBT  = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 5.6.5.0 (2013/06/07) 休憩の管理(buf2 ⇒ bufBT 名称変更)
712                StringBuilder buf1   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 下段の時刻データ
713//              StringBuilder buf2   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 休憩の管理
714                StringBuilder bufH   = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 3.8.1.4 (2006/03/13) 段組みヘッダー
715                StringBuilder bufcal = new StringBuilder( HybsSystem.BUFFER_SMALL );            // 5.5.4.0 (2012/07/02) 休日判定用
716                StringBuilder bufDY      = new StringBuilder( HybsSystem.BUFFER_SMALL );                // 5.7.0.0 (2013/11/03) 上段用
717                
718                String  last_title = null; // 5.7.0.0 (2013/11/03)
719                int             day_length = 0; // 5.7.0.0 (2013/11/03)
720                int     base = 2;               // 5.7.0.0 (2013/11/03) 時間単位の標準桁数
721                if( useTani ){ base = 4;}
722                
723                // daySpan      = "0700-2000";  // 開始時刻(HHmm-HHmm) 3.8.0.5 (2005/08/26)
724                // 分の少数計算を行います。加算は1時間(0100)単位です。
725//              int startTime = ym2int( daySpan.substring( 0,2 ),daySpan.substring( 2,4 ) ) ;
726//              int endTime   = ym2int( daySpan.substring( 5,7 ),daySpan.substring( 7 ) ) ;
727                // 5.6.1.2 (2013/02/22) 
728                int ad = daySpan.indexOf( '-' );
729                int startTime = hm2int( daySpan.substring( 0,ad ) ) ;
730                int endTime   = hm2int( daySpan.substring( ad+1 ) ) ;
731
732                // 開始時刻より終了時刻が同じか小さい場合は、翌日なので2400加算します。
733                if( endTime <= startTime ) { endTime += 2400; }
734
735                // 休憩時間を管理する BreakTimes オブジェクトを作成します。
736//              BreakTimes breakTimeObj = new BreakTimes( hourOfPixcel,breakTimes,breakTimeStyle,startTime,endTime );
737                BreakTimes breakTimeObj = new BreakTimes( hourOfPixcel/step,breakTimes,breakTimeStyle,startTime,endTime );
738
739                // 5.6.1.2 (2013/02/22) ベース時刻を管理する BreakTimes オブジェクトを作成します。(利用するクラスは同じ)
740                BreakTimes baseTimeObj = new BreakTimes( hourOfPixcel/step,baseTimes,baseTimeStyle,startTime,endTime );
741
742                // 現在時刻を求めておきます。 現在時刻に5分加算しておきます。(余計なお世話?)
743                Calendar rightNow = Calendar.getInstance();
744                rightNow.add( Calendar.MINUTE,5 );              // 5分 加算
745                int now = rightNow.get( Calendar.HOUR_OF_DAY ) ;
746
747                // 3.8.5.0 (2006/02/06)
748                boolean isDebug = isDebug();
749                if( isDebug ) {
750                        System.out.println( "startDate=" + startDate );
751                        System.out.println( "endDate  =" + endDate );
752                }
753
754                Calendar str = HybsSystem.getCalendar( startDate );
755                Calendar end = HybsSystem.getCalendar( endDate );
756
757                // 3.6.0.0 (2004/09/17) カレンダDB検索機能を追加
758                CalendarData calData = CalendarFactory.getCalendarData( calDB,arg1,arg2,arg3,arg4 );
759
760                // 1時間=hourOfPixcel(px) なので、1日分のピクセルを求めておく。(休憩時刻表示用)
761//              int dayOfPixel = (int)(hourOfPixcel * (endTime-startTime)/100.0 );
762//              int dayOfPixel = (int)(hourOfPixcel/step * (endTime-startTime)/100.0 );
763                int dayOfPixel = (int)(hourOfPixcel * Math.ceil((endTime-startTime)/100.0/step) ); // 5.5.4.0 (2012/07/02) 切り上げ
764
765                // 休憩表示における画面上の表示日数。これが、左のバイアス値として1日分と乗算される。
766                int totalDay = 0;
767
768                // 1日分の表示範囲の開始時刻とデータの表示開始時刻との差(オフセット)ピクセル
769//              int offsetPixel = (int)(hourOfPixcel * (startTime - (int)(str.get( Calendar.HOUR_OF_DAY )*100 + str.get( Calendar.MINUTE )*10.0/6.0))/100.0 );
770                int offsetPixel = (int)(hourOfPixcel/step * (startTime - (int)(str.get( Calendar.HOUR_OF_DAY )*100 + str.get( Calendar.MINUTE )*10.0/6.0))/100.0 );
771
772                // 3.8.1.4 (2006/03/13) 時間単位(h)の表示有無を USE_MULTI_CLM と関係させます。
773                // 3.8.1.6 (2006/04/25) 日や時間の単位表示を止め、2文字分(24ピクセル)化する。
774                final String tani ;
775//              if( useTani ) { tani = ( USE_MULTI_CLM ) ? "  " : "h " ; }
776//              if( useTani ) { tani = ( useMultiClm ) ? "  " : "h " ;  }               // 5.6.1.2 (2013/02/22) useMultiClm 追加
777                if( useTani ) { tani = "h " ;   }               // 5.6.5.0 (2013/06/07) useMultiClm を無視します。
778                else {                  tani = "";                                                              }
779
780                boolean modifyFlag = false;
781                int cnt = 0;    // 3.8.1.1 (2005/11/21)
782                while( str.before( end ) ) {    // 終了時間は、「含まない」仕様
783                        if( isDebug ) { System.out.println( "Calendar str =" + str.getTime() ); }       // 3.8.5.0 (2006/02/06)
784
785                        // 5.6.5.0 (2013/06/07) 日付と曜日の対応
786                        int day = str.get( Calendar.DATE );
787                        String dayStr = ((day >= 10) ? day : ("0" + day) ) + ((useTani) ? DAY_OF_WEEK_ja[str.get( Calendar.DAY_OF_WEEK )] : "") ;
788
789                        // 5.5.4.0 (2012/07/02) この場合は枠単位ではなく、日単位で出力する
790                        // skipHolidayは無視して、範囲内の全てのカレンダーを出力
791                        if(calData.isHoliday( str )){
792                                bufcal.append("1");
793                        }
794                        else{
795                                bufcal.append("0");
796                        }
797
798                        // 休日判断を、事業所カレンダを使用:休日なら、日付を進める。
799                        if( calData.isHoliday( str ) && skipHoliday ) {
800                                if( isDebug ) { System.out.println( "Holiday =" + str.getTime() ); }    // 3.8.5.0 (2006/02/06)
801                                str.add(Calendar.DATE, 1);
802                                continue;
803                        }
804
805                        // 3.8.1.1 (2005/11/21) 日付のツールチップ表示
806                        String ganttClass = "class=\"GNT_" + (cnt % 2) + "\"" ;
807
808                        Date dt = str.getTime();
809                        String title = format1.format( dt );
810                        buf1.append( "<span " ).append( ganttClass );
811                        buf1.append( " title=\"" ).append( title ).append( "\">" );
812                        
813                        // 5.7.0.0 (2013/11/03) 上段
814                        if( last_title != null & day_length > 0 ){
815                                makeHeaderMD(bufDY , day_length*base , 0 , last_title);
816                                day_length = 0;
817                        }
818                        last_title = format2.format( dt );
819                        
820                        if( isDebug ) { System.out.println( "title =" + title ); }      // 3.8.5.0 (2006/02/06)
821
822                        // 5.6.5.0 (2013/06/07) 色バー対応
823                        if( useMultiClm ) {
824                                if( cnt % 2 == 0 )      { bufH.append( EVEN_CLASS ); }          // 偶数の色
825                                else                            { bufH.append( ODD_CLASS  ); }          // 奇数の色
826                        }
827                        cnt++;          // 5.6.5.0 (2013/06/07) 他の処理は、cnt++ を先にしているが、ここでは初期設定指定ない為、cnt++ を、処理の後で行う。
828
829                        // 本日かどうかを判断する。
830                        boolean isToday = calData.isContainedToday( str,1 );
831
832                        int tmHd = startTime/100 ;
833                        int dayOut = tmHd;              // 3.8.1.4 (2006/03/13)
834                        boolean isTodayNow = false;             // 3.8.9.2 (2007/07/28) 時間ステップ対応
835
836                        for( int h=startTime; h<endTime; h+=100 ) {          // 加算は1時間単位
837                                if( isDebug ) { // 3.8.5.0 (2006/02/06)
838                                        System.out.println( "hour =" + h );
839                                        System.out.println( "tmHd =" + tmHd );
840                                }
841                                // 3.8.9.2 (2007/07/28) 時間ステップ対応
842                                isTodayNow = isTodayNow || ( isToday && tmHd == now );
843                                if( ( dayOut - tmHd ) % step != 0 ) { tmHd++; continue; }
844
845                                day_length++; // 5.7.0.0 (2013/11/03)
846                                
847                                if( tmHd >= 24 ) {
848                                        tmHd = 0;
849                                        // 3.8.1.1 (2005/11/21) 日付のツールチップを次の日に設定します。
850                                        Date dt2 = new Date( str.getTimeInMillis() + 24*3600*1000L );
851                                        title = format1.format( dt2 );
852                                        buf1.append( "</span><span " ).append( ganttClass );
853                                        buf1.append( " title=\"" ).append( title ).append( "\">" );
854                                }
855
856                                // 本日の現在時刻は、青色で示します。
857//                              if( isToday && tmHd == now ) {
858                                if( isTodayNow ) {
859                                        buf1.append( BLUE_COLOR );
860                                        bufH.append( BLUE_COLOR );
861                                        modifyFlag = true;
862                                        isTodayNow = false;             // 初期化
863                                }
864                                // 4.0.0.0 休日の場合は赤色で表示
865                                else if( calData.isHoliday( str ) && !skipHoliday ) {
866                                        buf1.append( RED_COLOR );
867                                        bufH.append( RED_COLOR );
868                                        modifyFlag = true;
869                                }
870
871                                // 実質表示日数(totalDay) * 1日分のピクセル(dayOfPixel) - オフセット(offsetPixel)
872//                              String bt = breakTimeObj.makeSpan( totalDay*dayOfPixel-offsetPixel,str,h );
873                                String bt = breakTimeObj.makeSpan( totalDay*dayOfPixel-offsetPixel,str,h,step );
874//                              if( bt != null ) { buf2.append( bt ); }
875                                if( bt != null ) { bufBT.append( bt ); }                // 5.6.5.0 (2013/06/07) 休憩の管理(buf2 ⇒ bufBT 名称変更)
876
877                                // 5.6.1.2 (2013/02/22) ベース時刻のタグを出力します。
878                                bt = baseTimeObj.makeSpan( totalDay*dayOfPixel-offsetPixel,str,h,step );
879//                              if( bt != null ) { buf2.append( bt ); }
880                                if( bt != null ) { bufBT.append( bt ); }                // 5.6.5.0 (2013/06/07) 休憩の管理(buf2 ⇒ bufBT 名称変更)
881
882                                // 時間当たりの文字数は、4文字: 文字列を詰める。
883                                if( tmHd < 10 ) { buf1.append( '0' ); }              // 桁数あわせ
884                                buf1.append( tmHd ).append( tani );                     // 3.8.1.4 (2006/03/13)
885
886                                // 3.8.1.4 (2006/03/13) 日付表示、時刻単位(h)削除、2段組(USE_MULTI_CLM)
887                                // 3.8.1.6 (2006/04/25) 日や時間の単位表示を止め、2文字分(24ピクセル)化する。
888//                              if( USE_MULTI_CLM ) {
889                                if( useMultiClm ) {                                             // 5.6.1.2 (2013/02/22) useMultiClm 追加
890//                                      if( ( dayOut - tmHd ) % 6 == 0 ) {
891                                        if( ( dayOut - tmHd ) == 0 ) {          // 5.6.5.0 (2013/06/07) 色バー対応
892//                                              if( useTani ) { bufH.append( title.substring( 8 ) ).append( "日" ); }
893//                                              if( useTani ) { bufH.append( title.substring( 8 ) ).append( "日 " ); }   // 5.6.4.3 (2013/05/24) ヘッダーずれ対応。"日" を2文字の、"日 " に修正。
894//                                              else {                  bufH.append( title.substring( 8 ) );                            }
895                                                bufH.append( dayStr );                  // 5.6.5.0 (2013/06/07) 先に日付+曜日の文字列を作成する。"日" を2文字の、"日 " に修正済み。
896                                        }
897                                        else {
898                                                if( useTani ) { bufH.append( "    " ); }
899                                                else {                  bufH.append( "  " );   }
900                                        }
901                                }
902
903                                if( modifyFlag ) {
904                                        buf1.append( END_SPAN );
905                                        bufH.append( END_SPAN );
906                                        modifyFlag = false;
907                                }
908                                tmHd++; // ヘッダーに記述する時刻
909                        }
910                        str.add(Calendar.DATE, 1);
911                        totalDay++ ;
912                        buf1.append( END_SPAN );
913                        if( useMultiClm ) { bufH.append( END_SPAN ); }  // 5.6.5.0 (2013/06/07) 色バー対応
914                }
915
916                // 3.8.1.4 (2006/03/13) 日付表示、時刻単位(h)削除、2段組(USE_MULTI_CLM)
917//              buf2.append( "<pre>" );
918//              buf1.append( "</pre>" );
919
920//              if( USE_MULTI_CLM ) {
921//              if( useMultiClm ) {                             // 5.6.1.2 (2013/02/22) useMultiClm 追加
922//                      buf2.append( bufH.toString() ).append( "<br />" );
923//              }
924                if( useMultiClm ) {                             // 5.6.1.2 (2013/02/22) useMultiClm 追加
925                        bufH.append( BR );
926                }
927                calStr = bufcal.toString(); // 5.5.4.0 (2012/07/02)
928                
929                // 5.7.0.0 (2013/11/03) 最後の上段
930                if( last_title != null & day_length > 0 ){
931                        makeHeaderMD(bufDY , day_length*base , 0 , last_title);
932                        day_length = 0;
933                }
934
935//              return buf2.append( buf1.toString() ).toString() ;
936                if( useMdheader ){ // 5.7.0.0 (2013/11/03) 月日を上段に表示する
937                        bufH = bufDY.append( BR ).append(bufH); 
938                }
939                return bufBT.append( "<pre>" ).append( bufH ).append( buf1 ).append( "</pre>" ).toString() ;
940        }
941
942        /**
943         * 時間軸での日ヘッダーデータを作成します。
944         *
945         * ヘッダーは、時間表示の場合に上段にMM/ddを表示します。
946         *
947         * @og.rev 5.7.0.0 (2013/11/07) 新規追加
948         *
949         * @param               bufH    ヘッダーを追記していく StringBuilder
950         * @param               fillCnt 日付欄の文字数カウント。通常は2*時間数か、4*時間数のどちらか。
951         * @param               mtCnt   月数に基づいた色の設定用の数字。(将来的な拡張用)
952         * @param               mdStr   ヘッダーに表示する文字列。月日(MM/dd)
953         *
954         * @return  ヘッダーが追記された StringBuilder
955         */
956        private StringBuilder makeHeaderMD( final StringBuilder bufH , final int fillCnt , final int mtCnt ,  final String mdStr ) {
957                if( mtCnt % 2 == 0 )    { bufH.append( EVEN_CLASS ); }          // 偶数色
958                else                                    { bufH.append( ODD_CLASS  ); }          // 奇数色
959                
960                // 表示すべき文字列が、表示すべき幅よりも小さい場合、スペースのみとする。
961                if( fillCnt < mdStr.length() ) {
962                        bufH.append( StringUtil.stringXFill(" ",fillCnt) );
963                }
964                // 大きい場合は、前後にスペースを入れて、センター配置
965                else {
966                        bufH.append( StringUtil.stringXFill(mdStr,fillCnt) );
967                }
968
969                bufH.append( END_SPAN );
970
971                return bufH;
972        }
973
974        /**
975         * 上段・下段のフォーマットと、加算日に応じたヘッダー文字列を作成します。
976         *
977         * @param       upper   上段の表示フォーマット
978         * @param       lower   下段の表示フォーマット
979         * @param       add     表示日付けの加算
980         * @param       useMonth        月日表示でなく、月表示のみにする
981         * 
982         * @og.rev 5.6.1.2 (2013/02/22) 新規作成
983         * @og.rev 5.6.2.3 (2013/03/22) 日付の終了日は、「含む」に変更
984         *
985         * @return  ヘッダー文字列
986         */
987        private String makeZoomStack( final String upper ,final String lower ,final int add, final boolean useMonth ) {
988                DateFormat format1 = new SimpleDateFormat( upper,Locale.JAPAN );
989                DateFormat format2 = new SimpleDateFormat( lower,Locale.JAPAN );
990
991                DateFormat formatCal = new SimpleDateFormat( "yyyyMMdd",Locale.JAPAN );
992
993                // 5.5.8.3 (2012/11/17) スタック用にカレンダー枠の情報を保持(開始、休日判定、次枠開始)
994                ArrayList<String[]> calList = new ArrayList<String[]>();                    // 個人的には Listを渡す方が好き
995                String[] calArray = new String[3]; // 開始、休日判定、次枠開始
996
997                Calendar str = HybsSystem.getCalendar( startDate );
998                Calendar end = HybsSystem.getCalendar( endDate );
999
1000                // 週単位の場合の特殊処理。
1001                // 年の第一週を完全な一週間分(7日間)として、設定します。
1002                if( zoom == 41 ) {              // ViewStackTableParam.STACK_ZOOM_WEEK
1003                        str.setMinimalDaysInFirstWeek( 7 );
1004                        format1.setCalendar( str );
1005                        format2.setCalendar( str );
1006                }
1007
1008                if( useMonth ){
1009                        str.set(Calendar.DAY_OF_MONTH, 1);
1010                        startDate = new SimpleDateFormat( "yyyyMMdd",Locale.JAPAN ).format(str.getTime());
1011                }
1012
1013                StringBuilder buf1   = new StringBuilder( HybsSystem.BUFFER_SMALL );
1014                StringBuilder buf2   = new StringBuilder( HybsSystem.BUFFER_SMALL );
1015                StringBuilder bufcal = new StringBuilder( HybsSystem.BUFFER_SMALL ); 
1016
1017                //  カレンダDB検索機能
1018                CalendarData calData = CalendarFactory.getCalendarData( calDB,arg1,arg2,arg3,arg4 );
1019
1020                boolean modifyFlag = false;
1021                // 5.6.2.3 (2013/03/22) 日付の終了日は、「含む」に変更
1022//              while( str.before( end ) ) {
1023                while( str.compareTo( end ) <= 0 ) {
1024                        Date dt = str.getTime();
1025                        calArray[0] = formatCal.format( dt ); // 5.5.8.3 (2012/11/17)
1026
1027                        // 本日は、青色で示します。
1028                        if( calData.isContainedToday( str,add ) ) {
1029                                buf1.append( BLUE_COLOR );
1030                                buf2.append( BLUE_COLOR );
1031                                bufcal.append( "0" ); 
1032                                calArray[1] = "0"; // 5.5.8.3 (2012/11/17)
1033                                modifyFlag = true;
1034                        }
1035
1036                        // 休日判断を、事業所カレンダを使用
1037                        // modifyFlag が立っていない場合 を条件に追加します。
1038                        if( !modifyFlag && add == 1 && calData.isHoliday( str ) && !useMonth) {
1039                                buf1.append( RED_COLOR );
1040                                buf2.append( RED_COLOR );
1041                                bufcal.append( "1" ); // 休日
1042                                calArray[1] = "1"; // 5.5.8.3 (2012/11/17)
1043                                modifyFlag = true;
1044                        }
1045
1046                        buf1.append( format1.format( dt ) );
1047                        buf2.append( format2.format( dt ) );
1048
1049                        if( modifyFlag ) {
1050                                buf1.append( END_SPAN );
1051                                buf2.append( END_SPAN );
1052                                modifyFlag = false;
1053                        }
1054                        else{
1055                                bufcal.append( "0" ); 
1056                                calArray[1] = "0"; // 5.5.8.3 (2012/11/17)
1057                        }
1058
1059                        // カレンダーを進める
1060                        if( useMonth ){
1061                                str.add(Calendar.MONTH, add);
1062                        }
1063                        else{
1064                                str.add(Calendar.DATE, add);
1065                        }
1066
1067                        dt = str.getTime();
1068                        calArray[2] = formatCal.format( dt ); // 5.5.8.3 (2012/11/17)
1069                        calList.add( calArray.clone() );
1070                }
1071
1072                // スタックガント用の特別な処理。
1073                // 上位の ViewForm_HTMLStackedGanttTable クラスに対して、「開始、休日判定、次枠開始」リストを渡します。
1074                ViewFormTag viewform = (ViewFormTag)findAncestorWithClass( this,ViewFormTag.class );
1075                viewform.setViewArrayList( calList ); 
1076
1077                calStr = bufcal.toString(); 
1078
1079                return "<pre>" + buf1.toString() + BR + buf2.toString() + "</pre>";
1080        }
1081
1082        /**
1083         * ganttHeaderの属性情報をdisplay:noneで作成します。
1084         * ganttHeaderというタグで、id,class共にganttHeaderDataという名称で出力します。
1085         *
1086         * @og.rev 5.5.4.0 (2012/07/02) 新規作成
1087         * @og.rev 5.6.1.2 (2013/02/22) baseTimes 追加
1088         *
1089         * @return  ヘッダー情報の文字列
1090         */
1091        private String makeHeaderData() {
1092
1093                StringBuilder buf1 = new StringBuilder( HybsSystem.BUFFER_SMALL );
1094
1095                buf1.append( "\n" )
1096                        .append( "<ganttHeader style='display:none' id='ganttHeaderData' class='ganttHeaderData' " )
1097                        .append( "startDate='"  ).append( startDate             ).append( "' " )
1098                        .append( "endDate='"    ).append( endDate               ).append( "' " )
1099                        .append( "zoom='"               ).append( zoom                  ).append( "' " )
1100                        .append( "daySpan='"    ).append( daySpan               ).append( "' " )
1101                        .append( "calDB='"              ).append( calStr                ).append( "' " )
1102                        .append( "breakTimes='" ).append( breakTimes    ).append( "' " )
1103                        .append( "baseTimes='"  ).append( baseTimes             ).append( "' " )                // 5.6.1.2 (2013/02/22) baseTimes 追加
1104                        .append( "skipHoliday='" ).append( skipHoliday  ).append( "' " )
1105                        .append( "useMultiClm='" ).append( useMultiClm  ).append( "' " )                // 5.6.1.2 (2013/02/22) useMultiClm 追加
1106                        .append( " />" );
1107
1108                return buf1.toString();
1109        }
1110
1111        /**
1112         * 【TAG】表示開始日付けを設定します(yyyyMMdd または、yyyyMMddHHmm 形式)。
1113         *
1114         * @og.tag
1115         * この値は、ヘッダーの先頭に表示する日付けを指定します。
1116         * 通常の日付ヘッダーの場合は、 yyyyMMdd 形式ですが、時間ヘッダーの場合は、
1117         * yyyyMMddHHmm 形式で指定します。
1118         *
1119         * @param       val 表示開始日付(yyyyMMdd または、yyyyMMddHHmm 形式)
1120         */
1121        public void setStartDate( final String val ) {
1122                startDate = nval( getRequestParameter( val ),startDate );
1123        }
1124
1125        /**
1126         * 【TAG】表示最終日を設定します(yyyyMMdd または、yyyyMMddHHmm 形式)。
1127         *
1128         * @og.tag
1129         * 表示開始日から終了日までを、zoom 変数の値に応じてヘッダーラベルを
1130         * 作成します。
1131         * 通常の日付ヘッダーの場合は、 yyyyMMdd 形式ですが、時間ヘッダーの場合は、
1132         * yyyyMMddHHmm 形式で指定します。
1133         *
1134         * @param       val 表示最終日(yyyyMMdd または、yyyyMMddHHmm 形式)
1135         */
1136        public void setEndDate( final String val ) {
1137                endDate = nval( getRequestParameter( val ),endDate );
1138        }
1139
1140        /**
1141         * 【TAG】1日の開始終了時間を24時間形式(HHmm-HHmm または HH-HH)で設定します(初期値:0700-2000)。
1142         *
1143         * @og.tag
1144         * この値は、1日の開始終了時間を指定します。
1145         * 開始時刻は、内部で1時間単位に変換されます。8時30分〜は、8時〜になります。
1146         * 終了時間は、その時間を「含みません」
1147         * 開始時刻より終了時刻が小さい場合は、翌日への日またぎとして計算します。
1148         * たとえば、夜勤等で、17:00-07:00 という指定が可能です。
1149         * 初期値は、朝の7:00から夜の20:00までです。(0700-2000)です。
1150         *
1151         * @og.rev 3.8.0.5 (2005/08/26) 本日は、青色で示します。
1152         * @og.rev 5.6.1.2 (2013/02/22) daySpan(時刻表示範囲)は、内部では1時間単位
1153         *
1154         * @param       val 開始終了時間(HHmm-HHmm)形式
1155         */
1156        public void setDaySpan( final String val ) {
1157                daySpan = nval( getRequestParameter( val ),daySpan );
1158
1159                // 5.6.1.2 (2013/02/22) daySpan(時刻表示範囲)は、内部では1時間単位
1160                if( daySpan.length() == 5 && daySpan.charAt(2) == '-' ) {
1161                        daySpan = daySpan.substring( 0,2 ) + "00-" + daySpan.substring( 3 ) + "00" ;    // HH-HH ⇒ HH00-HH00
1162                }
1163                else if( daySpan.length() == 9 && daySpan.charAt(4) == '-' ) {
1164                        daySpan = daySpan.substring( 0,2 ) + "00-" + daySpan.substring( 5 ) ;                   // HHmm-HHmm  ⇒ HH00-HHmm
1165                }
1166                else {
1167//              if( daySpan.length() != 9 || daySpan.charAt(4) != '-' ) {               // 5.6.1.2 (2013/02/22)
1168//                      String errMsg = "1日の開始終了時間は24時間制で(HHmm-HHmm)形式で指定してください。"
1169                        String errMsg = "1日の開始終了時間は24時間制で(HHmm-HHmm または HH-HH)形式で指定してください。"
1170                                        + " value=[" + val + "]"
1171                                        + " daySpan=[" + daySpan + "]" ;                // 5.1.8.0 (2010/07/01) errMsg 修正
1172                        throw new HybsSystemException( errMsg );
1173                }
1174        }
1175
1176        /**
1177         * 【TAG】ズーム変数(0〜9,10,11,12,20〜31,40〜42)を設定します(初期値:2)。
1178         *
1179         * @og.tag
1180         * CSSファイルでの定義と、背景画像との関係で、作成します。
1181         * ズーム変数は、CSSファイルや、JavaScript、PL/SQLと連動して、日付間隔
1182         * あたりのピクセルを計算して、ヘッダーを作成しています。
1183         * また、現在の標準的なクライアントでの換算になる為、高解像度のディスプレイや
1184         * 特殊設定された環境では、表示間隔にずれが発生する可能性があります。
1185         *
1186         *    ZOOM  ラベル        日数ピクセル変換率          ヘッダ上      ヘッダ下    1文字(CSS)
1187         *  ========================================================================================
1188         *      0 : 1週間 日数 *  8 * 6       48    48px =  1日  [02/   ]      [23(EE)]       8px
1189         *      1 : 2週間 日数 *  8 * 3       24    24px =  1日  [02/]         [23 ]          8px
1190         *      2 : 1ヶ月 日数 *  12* 1       12    12px =  1日  [2]           [3]           12px
1191         *      3 : 2ヶ月 日数 *  8 * 7  /  7  8    56px =  7日  [2004/  ]     [02/03  ]      8px
1192         *      4 : 3ヶ月 日数 *  8 * 7  / 14  4    56px = 14日  [2004/  ]     [02/03  ]      8px
1193         *      5 : 4ヶ月 日数 *  9 * 10 / 30  3    90px = 30日  [2004/     ]  [02/03     ]   9px
1194         *      6 : 6ヶ月 日数 * 10 / 6  / 30  2    60px = 30日  [2004/ ]      [02/03 ]      10px
1195         *      7 : 1年   日数 *  9 / 10 / 90  1    90px = 90日  [2004/     ]  [02/03     ]   9px
1196         *      8 : 2年   日数 *  9 / 10 /180  0.5  90px =180日  [2004/     ]  [02/03     ]   9px
1197         *      9 : 3年   日数 * 10 / 6  /180  0.33 60px =180日  [2004/ ]      [02/03 ]      10px
1198         *     10 : 週単位 日数 *  8 / 3  /  7  3.43 24px =  7日  [19W]         [12 ]          8px
1199         *     11 : 予約済み(他物10件使用済み)
1200         *     12 : 予約済み(他物 8件使用済み)
1201         *     13 : 日(週) 日数 *  8 * 2       16    16px =  1日  [23]          [EE]           8px
1202         *  ========================================================================================
1203         *     20 :  1時間   時間 * 12 * 4        48 48px = 1時間 [02EE]        [07h ]        12px
1204         *     21 :  1時間2  時間 * 12 * 2        24 24px = 1時間 [02]          [07]          12px
1205         *     22 :  2時間   時間 * 12 * 4  /  2  24 48px = 2時間 [02EE]        [07h ]        12px
1206         *     23 :  2時間2  時間 * 12 * 2  /  2  12 24px = 2時間 [02]          [07]          12px
1207         *     24 :  4時間   時間 * 12 * 4  /  4  12 48px = 4時間 [02EE]        [07h ]        12px
1208         *     25 :  4時間2  時間 * 12 * 2  /  4   6 24px = 4時間 [02]          [07]          12px
1209         *     26 :  6時間   時間 * 12 * 4  /  6   8 48px = 6時間 [02EE]        [07h ]        12px
1210         *     27 :  6時間2  時間 * 12 * 2  /  6   4 24px = 6時間 [02]          [07]          12px
1211         *     28 :  8時間   時間 * 12 * 4  /  8   6 48px = 8時間 [02EE]        [07h ]        12px
1212         *     29 :  8時間2  時間 * 12 * 2  /  8   3 24px = 8時間 [02]          [07]          12px
1213         *     30 : 12時間   時間 * 12 * 4  / 12   4 48px =12時間 [02EE]        [07h ]        12px
1214         *     31 : 12時間2  時間 * 12 * 2  / 12   2 24px =12時間 [02]          [07]          12px
1215         *  ========================================================================================
1216         *     40 : 積上(日)                    48   48px =  1日  [02/   ]      [23(EE)]       8px
1217         *     41 : 積上(週)                    3.43 48px =  7日  [19W]         [12 ]          8px
1218         *     42 : 積上(月) 月数 * 1            1   90px = 30日  [2004/     ]  [02/03     ]   9px
1219         *     43 : 日単位ヘッダー予約済み
1220         *     〜
1221         *     49 : 日単位ヘッダー予約済み
1222         *
1223         * @og.rev 5.7.6.2 (2014/05/16) stackHeaderタグの互換機能として、DAY⇒40,WEEK⇒41,MONTH⇒42 対応する。
1224         *
1225         * @param       val ズーム変数(0〜9,10,11,12,20〜31,40〜42)
1226         */
1227        public void setZoom( final String val ) {
1228//              zoom = nval( getRequestParameter( val ),zoom );
1229
1230                String zm = nval( getRequestParameter( val ),null );
1231
1232                // 6.0.0.1 (2014/04/25) zoom の、DAY⇒40,WEEK⇒41,MONTH⇒42 対応
1233                if( ViewStackTableParam.STACK_ZOOM_DAY.equalsIgnoreCase( zm ) ) {
1234                        zoom = 40;
1235                } else if( ViewStackTableParam.STACK_ZOOM_WEEK.equalsIgnoreCase( zm ) ) {
1236                        zoom = 41;
1237                } else if( ViewStackTableParam.STACK_ZOOM_MONTH.equalsIgnoreCase( zm ) ) {
1238                        zoom = 42;
1239                }
1240                else {
1241                        zoom = nval( zm,zoom );
1242                }
1243
1244                if( zoom < 0 || (13 < zoom && zoom < 20) || (31 < zoom && zoom < 40) || 42 < zoom ) {
1245                        String errMsg = "ズーム変数は、(0〜9,10,11,12,20〜31,40〜42)の範囲で指定してください。"
1246                                        + " zoom=[" + val + "]" ;
1247                        throw new HybsSystemException( errMsg );
1248                }
1249        }
1250
1251        /**
1252         * 【TAG】DB検索するDBを指定します。
1253         *
1254         * @og.tag
1255         * カレンダデータは、システムパラメータ の CalendarQuery_**** で
1256         * 指定する、CalendarQuery クラスの QUERY 文で、実際に取得します。
1257         * 上記の **** 部分に、ここで指定するキーワードを設定して置きます。
1258         * 通常は、データベースID (GE13, ZY01 など)を指定します。
1259         * このキーワードに対する実装クラスを、先のシステムパラメータ の
1260         * キーワード以下に記述しておきます。
1261         * {@og.doc03Link calDB CalendarQuery_****}
1262         *
1263         * @og.rev 3.6.0.0 (2004/09/17) DB検索するDBのキー
1264         *
1265         * @param       db      DB検索するDBを指定
1266         */
1267        public void setCalDB( final String db ) {
1268                calDB = nval( getRequestParameter( db ),calDB );
1269        }
1270
1271        /**
1272         * 【TAG】時間軸での休憩時間の開始-終了時刻をカンマ区切りで複数指定します。
1273         *
1274         * @og.tag
1275         * 休憩時間は、HHmm-HHmm形式、または、yyyyMMddHHmm-HHmm、または、
1276         * yyyyMMddHHmm-yyyyMMddHHmm形式で複数指定できます。
1277         * これは、開始-終了というハイフン形式でつなげます。
1278         * このセットを、カンマで複数指定できます。
1279         * 例えば、200508201200-1245,200508201300-1315 という感じです。
1280         * - の前後が、4桁の場合は、HHmm-HHmm 形式として、日付に関係なく、常にこの時分
1281         * で休憩が入るという認識をします。つまり、開始は、12桁か、4桁の日付形式、
1282         * 終了も、12桁か、4桁の日付形式になります。
1283         *
1284         * @og.rev 3.8.0.5 (2005/08/26) 新規追加
1285         * @og.rev 3.8.0.7 (2005/09/20) 日付またがり追加追加
1286         *
1287         * @param       times   休憩時間の開始-終了時刻(CSV区切り)
1288         */
1289        public void setBreakTimes( final String times ) {
1290                breakTimes = nval( getRequestParameter( times ),null );
1291        }
1292
1293        /**
1294         * 【TAG】時間軸での休憩時間の表示スタイルを設定します。
1295         *
1296         * @og.tag
1297         * 通常は、ヘッダーのトップからの位置と、色です。
1298         * それ以外にも、スタイルシート属性(キー:値;) というセットを指定できます。
1299         * class="breakTime" を出力していますので、そちらを使用したい場合は、breakTimeStyleを無効化してください。
1300         * そうしないと、こちらは、直接 style属性で設定しているので、強いです。
1301         * 初期値は、top:20px;background-color:yellow;filter:alpha(opacity=60);opacity:0.60; です。
1302         * IE8以下のために、filter:alpha(opacity=60); しています。
1303         * 設定の後ろに、; を付ける様にしてください。
1304         *
1305         * @og.rev 3.8.0.5 (2005/08/26) 新規追加
1306         *
1307         * @param       style   休憩時間の表示スタイル
1308         */
1309        public void setBreakTimeStyle( final String style ) {
1310                breakTimeStyle = nval( getRequestParameter( style ),breakTimeStyle );
1311        }
1312
1313        /**
1314         * 【TAG】時間軸でのベース時刻の開始時刻をカンマ区切りで複数指定します。
1315         *
1316         * @og.tag
1317         * ベース時刻は、HHmm形式、または、yyyyMMddHHmm形式で複数指定できます。
1318         * このセットを、カンマで複数指定できます。
1319         * 例えば、1700,200508201300 という感じです。
1320         *
1321         * @og.rev 5.6.1.2 (2013/02/22) 新規追加
1322         *
1323         * @param       times   ベース時刻の開始時刻(CSV区切り)
1324         */
1325        public void setBaseTimes( final String times ) {
1326                baseTimes = nval( getRequestParameter( times ),null );
1327        }
1328
1329        /**
1330         * 【TAG】時間軸でのベース時刻の表示スタイルを設定します。
1331         *
1332         * @og.tag
1333         * 通常は、ベース時刻の幅と、ヘッダーのトップからの位置と、色です。
1334         * それ以外にも、スタイルシート属性(キー:値;) というセットを指定できます。
1335         * 初期値は、top:20px;background-color:transparent;border-left:2px dashed red; です。
1336         * 設定の後ろに、; を付ける様にしてください。
1337         *
1338         * @og.rev 5.6.1.2 (2013/02/22) 新規追加
1339         *
1340         * @param       style   ベース時刻の表示スタイル
1341         */
1342        public void setBaseTimeStyle( final String style ) {
1343                baseTimeStyle = nval( getRequestParameter( style ),baseTimeStyle );
1344        }
1345
1346        /**
1347         * 【TAG】DB検索する場合の第1のキーを指定します。
1348         *
1349         * @og.tag
1350         * 例えば、GE13, ZY01 では、事業所コード(CDJGS)を設定します。
1351         * この値は、システムパラメータ の CalendarQuery_**** で
1352         * 指定する、CalendarQuery クラスの QUERY 文に依存します。
1353         * データベース定義の統一を望むところです。
1354         *
1355         * @og.rev 3.6.0.0 (2004/09/17) DB検索の第1キー(事業所コードなど)を追加
1356         *
1357         * @param       arg DB検索の第1キー(事業所コードなど)
1358         */
1359        public void setArg1( final String arg ) {
1360                arg1 = nval( getRequestParameter( arg ),arg1 );
1361        }
1362
1363        /**
1364         * 【TAG】DB検索する場合の第2のキーを指定します。
1365         *
1366         * @og.tag
1367         * 例えば、TP652 では、事業部コード(CDJGS) と 物件工程コード(CDKTEI)の2つの
1368         * キーで、カレンダを取得します。(+年月で、行を決定)
1369         * 引数が、2つまで対応しています
1370         * この値は、システムパラメータ の CalendarQuery_**** で
1371         * 指定する、CalendarQuery クラスの QUERY 文に依存します。
1372         * データベース定義の統一を望むところです。
1373         *
1374         * @og.rev 3.6.0.0 (2004/09/17) DB検索の第2キー(WCコードなど)を追加
1375         *
1376         * @param       arg DB検索の第2キー(WCコードなど)
1377         */
1378        public void setArg2( final String arg ) {
1379                arg2 = nval( getRequestParameter( arg ),arg2 );
1380        }
1381
1382        /**
1383         * 【TAG】DB検索する場合の第3のキーを指定します。
1384         *
1385         * @og.tag
1386         * この値は、システムパラメータ の CalendarQuery_**** で
1387         * 指定する、CalendarQuery クラスの QUERY 文に依存します。
1388         * データベース定義の統一を望むところです。
1389         *
1390         * @og.rev 3.6.0.0 (2004/09/17) DB検索の第3キーを追加
1391         *
1392         * @param       arg DB検索の第3キー
1393         */
1394        public void setArg3( final String arg ) {
1395                arg3 = nval( getRequestParameter( arg ),arg3 );
1396        }
1397
1398        /**
1399         * 【TAG】DB検索する場合の第4のキーを指定します。
1400         *
1401         * @og.tag
1402         * この値は、システムパラメータ の CalendarQuery_**** で
1403         * 指定する、CalendarQuery クラスの QUERY 文に依存します。
1404         * データベース定義の統一を望むところです。
1405         *
1406         * @og.rev 3.6.0.0 (2004/09/17) DB検索の第4キーを追加
1407         *
1408         * @param       arg DB検索の第4キー
1409         */
1410        public void setArg4( final String arg ) {
1411                arg4 = nval( getRequestParameter( arg ),arg4 );
1412        }
1413
1414        /**
1415         * 【TAG】時間ガントで休日を表示する/しないを設定します
1416         *              (初期値:USE_GANTTHEADER_SKIP_HOLIDAY[={@og.value org.opengion.hayabusa.common.SystemData#USE_GANTTHEADER_SKIP_HOLIDAY}])。
1417         *
1418         * @og.tag
1419         * この値をfalseにすると、時間ガントでも休日が赤色で表示
1420         * されるようになります。trueにした場合は、休日は表示されません。
1421         * (初期値:システム定数のUSE_GANTTHEADER_SKIP_HOLIDAY[={@og.value org.opengion.hayabusa.common.SystemData#USE_GANTTHEADER_SKIP_HOLIDAY}])。
1422         *
1423         * @og.rev 4.0.0.0 (2007/09/07) 新規作成
1424         *
1425         * @param       skipHol 休日をスキップするかどうか。
1426         * @see         org.opengion.hayabusa.common.SystemData#USE_GANTTHEADER_SKIP_HOLIDAY
1427         */
1428        public void setSkipHoliday( final String skipHol) {
1429                skipHoliday = nval( getRequestParameter( skipHol ),skipHoliday );
1430        }
1431
1432        /**
1433         * 【TAG】時間ガントで2段組を使用する/しないを設定します
1434         *              (初期値:USE_GANTTHEADER_MULTIPLE_COLUMN[={@og.value org.opengion.hayabusa.common.SystemData#USE_GANTTHEADER_MULTIPLE_COLUMN}])。
1435         *
1436         * @og.tag
1437         * ガントヘッダーにおいて、時間ヘッダーの上段に日付を、下段の時間軸の(h)の削除を行います。
1438         * 日付は、表示開始時刻の上と、それの6時間ごとに表示します。
1439         * (初期値:システム定数のUSE_GANTTHEADER_MULTIPLE_COLUMN[={@og.value org.opengion.hayabusa.common.SystemData#USE_GANTTHEADER_MULTIPLE_COLUMN}])。
1440         *
1441         * @og.rev 5.6.1.2 (2013/02/22) 新規作成
1442         *
1443         * @param       multiClm        時間ガントで2段組を使用するかどうか(true:する/false:しない)。
1444         * @see         org.opengion.hayabusa.common.SystemData#USE_GANTTHEADER_MULTIPLE_COLUMN
1445         */
1446        public void setUseMultiClm( final String multiClm ) {
1447                useMultiClm = nval( getRequestParameter( multiClm ),useMultiClm );
1448        }
1449
1450        /**
1451         * 日付、時刻の文字列を時間整数に変換します。
1452         *
1453         * 時間を扱う場合は、厄介なのは、時間と分の単位の違いです。
1454         * 分に換算してしまうと、時間の取得に60進数で扱う必要が出てきます。
1455         * そこで、単純に時間に換算するのではなく、1時間を100として、
1456         * 分を0から99までの整数に換算して計算しています。
1457         * これにより時間の足し算や引き算が可能になり、かつ、時間を求めるのに
1458         * 100で割るだけで求めることが可能になります。
1459         *
1460         * @og.rev 5.6.1.2 (2013/02/22) 廃止
1461         *
1462         * @param       yy      時間の文字列
1463         * @param       mm      分の文字列
1464         *
1465         * @return 1時間を100として、分を0から99までの整数に換算した値
1466         */
1467//      private static int ym2int( final String yy,final String mm ) {
1468//              return (int)(Integer.parseInt( yy ) * 100 + Integer.parseInt( mm )*10.0/6.0 ) ;
1469//      }
1470
1471        /**
1472         * 日付、時刻の文字列を時間整数に変換します。
1473         *
1474         * 時間を扱う場合は、厄介なのは、時間と分の単位の違いです。
1475         * 分に換算してしまうと、時間の取得に60進数で扱う必要が出てきます。
1476         * そこで、単純に時間に換算するのではなく、1時間を100として、
1477         * 分を0から99までの整数に換算して計算しています。
1478         * これにより時間の足し算や引き算が可能になり、かつ、時間を求めるのに
1479         * 100で割るだけで求めることが可能になります。
1480         *
1481         * ここでは、引数に、HHmm 、 HHmmss 、yyyyMMddHHmm 、yyyyMMddHHmmss 、null が扱えます。
1482         * null の場合は、-1 を返します。
1483         * yyyyMMdd 部分は、無視されます。
1484         *
1485         * @og.rev 5.6.1.2 (2013/02/22) 日付、秒、null 対応
1486         *
1487         * @param       hhmm    時分の文字列
1488         *
1489         * @return 1時間を100として、分を0から99までの整数に換算した値
1490         */
1491        private static int hm2int( final String hhmm ) {
1492                int rtn = -1;
1493
1494                if( hhmm != null ) {
1495                        int len = hhmm.length();
1496                        String hh = null;
1497                        String mm = null;
1498                        if( len == 4 || len == 6 ) {                    // HHmm 、HHmmss
1499                                hh = hhmm.substring( 0,2 );
1500                                mm = hhmm.substring( 2,4 );
1501                        }
1502                        else if( len == 12 || len == 14 ) {             // yyyyMMddHHmm 、yyyyMMddHHmmss
1503                                hh = hhmm.substring( 8,10 );
1504                                mm = hhmm.substring( 10,12 );
1505                        }
1506                        else {
1507                                String errMsg = "指定できる時間形式は、HHmm 、HHmmss 、yyyyMMddHHmm 、yyyyMMddHHmmss です。"
1508                                                        + HybsSystem.CR
1509                                                        + "hm2int=[" + hhmm + "]" ;
1510                                throw new HybsSystemException( errMsg );
1511                        }
1512                        rtn = (int)(Integer.parseInt( hh ) * 100 + Integer.parseInt( mm )*10.0/6.0 ) ;
1513                }
1514
1515                return rtn;
1516        }
1517
1518        /**
1519         * 休憩時間のデータを管理する内部クラスです。
1520         *
1521         * @og.rev 3.8.0.7 (2005/09/20) 内部クラス新規作成
1522         * @og.group 画面部品
1523         *
1524         * @version  4.0
1525         * @author      Kazuhiko Hasegawa
1526         * @since    JDK5.0,
1527         */
1528        private static class BreakTimeData {
1529                private final String startDay   ;               // 開始日付。null の場合は、毎日
1530                private final int        startTime      ;               // 開始時刻のhm2int変換済み値
1531                private final int        timeSpan       ;               // 開始時刻と終了時刻の時間差(hm2int変換済み)
1532                private final String viewTime   ;               // ツールチップ表示用の文字列(HHmm-HHmm)
1533
1534                /**
1535                 * コンストラクター
1536                 *
1537                 * 開始日付(startDay)、開始時刻(startTime)、時間差(timeSpan)、表示ラベル(viewTime)
1538                 * を指定して、休憩時間のデータオブジェクトを構築します。
1539                 * 開始日付(startDay)は、null の場合は、毎日、つまり、定常的な休憩時刻として
1540                 * 認識します。日付が指定された場合は、その日のみの特別な休憩時間と認識します。
1541                 * 開始時刻は、hm2int変換済み値で、1時間が100となり、分は、10進数に変換されている
1542                 * 値として認識します。7:30 の場合は、750 という値になります。
1543                 * 開始時刻と終了時刻の時間差(timeSpan)も hm2int変換済み値です。
1544                 * 表示用の文字列(viewTime)は、休憩時間の HTML表記時の title 属性として
1545                 * 設定される為、マウスオーバー時のツールチップに現れます。
1546                 *
1547                 * @param       startDay        yyyyMMdd 形式の開始日付。null の場合は、毎日
1548                 * @param       startTime       開始時刻のhm2int変換済み値
1549                 * @param       timeSpan        開始時刻と終了時刻の時間差(hm2int変換済み)
1550                 * @param       viewTime        ツールチップ表示用の文字列(HHmm-HHmm)
1551                 * @return 含まれる(対象)場合は、true そうでない場合は、false
1552                 */
1553                BreakTimeData( final String startDay,final int startTime,final int timeSpan,final String viewTime ) {
1554                        this.startDay   = startDay;
1555                        this.startTime  = startTime;
1556                        this.timeSpan   = timeSpan;
1557                        this.viewTime   = viewTime;
1558                }
1559
1560                /**
1561                 * 指定の日付と時刻が、この BreakTimeData の開始日時とマッチするかどうかをチェックします。
1562                 *
1563                 * 開始日時とマッチするとは、内部日付がマッチし、開始時刻が、指定の time の
1564                 * 1時間(+100)*stepの範囲に含まれている場合を指します。(true を返します。)
1565                 * 内部の日付(startDay)が null の場合は、毎日が対象となります。
1566                 * 開始時刻がマッチした場合は、timeSpan 分だけの幅を持った休憩時間を認識します。
1567                 * 境界条件の都合で、timeSpan == 0 の状態も存在しますが、これはマッチしないと判断します。
1568                 *
1569                 * @og.rev 3.8.1.1 (2005/11/21) timeSpan が 0 より大きい場合 条件追加
1570                 * @og.rev 3.8.9.2 (2007/07/28) 時間間隔パラメータ追加
1571                 *
1572                 * @param       inDay   yyyyMMdd 形式の日付。
1573                 * @param       time    休憩時間の開始時刻のhm2int変換済み値
1574                 * @param       step    時間間隔
1575                 * @return 含まれる(対象)場合は、true そうでない場合は、false
1576                 */
1577//              boolean startsWith( final String inDay,final int time ) {
1578                boolean startsWith( final String inDay,final int time,final int step ) {
1579                        return ( timeSpan > 0 &&
1580                                         time <= startTime &&
1581                                         startTime < time+100*step &&
1582                                         ( startDay == null || inDay.equals( startDay ) ) );
1583                }
1584
1585                /**
1586                 * 休憩時間を表す SPANタグを作成します。
1587                 *
1588                 * 1時間=hourOfPixcel(px) で換算します。分は、すでに分数計算(hm2int)済み
1589                 *
1590                 * @og.rev 3.8.8.4 (2007/02/17) class="breaktime"  追加
1591                 * @og.rev 5.6.1.2 (2013/02/22) ベース時刻対応。width が 0 の場合は、2 をセット
1592                 *
1593                 * @param       offset  表示開始ピクセル数(実質表示日数 * 1日分のピクセル - オフセット)
1594                 * @param       hourOfPixcel    1時間あたりのピクセル数
1595                 * @param       breakTimeStyle  休憩時間の指定に追加するスタイル属性
1596                 * @return 休憩時間を表す SPANタグ
1597                 */
1598                String getBreakTime( final int offset,final int hourOfPixcel,final String breakTimeStyle ) {
1599                        int left  = offset + (startTime*hourOfPixcel/100) ;
1600                        int width = (timeSpan*hourOfPixcel/100) ;
1601                        if( width == 0 ) { width = 2; }         // 5.6.1.2 (2013/02/22) ベース時刻対応。width が 0 の場合は、2 をセット
1602
1603                        return "<span class=\"breaktime\" title=\"" + viewTime + "\""
1604                                        + " style=\"position:absolute;z-index:100;height:500000px;"
1605                                        + "left:"       + left  + "px;"
1606                                        + "width:"      + width + "px;"
1607                                        + breakTimeStyle        + "\" ></span>"
1608                                        + HybsSystem.CR ;
1609                }
1610        }
1611
1612        /**
1613         * 休憩時間を管理する内部クラスです。
1614         * 
1615         * 内部的に、休憩時間以外に、ベース時刻も処理できるようにします。
1616         * これは、終了時刻を指定されていない場合でも対応できるようにすることを意味します。
1617         * また、時間指定方法を、時分だけでなく、時分秒指定時でも処理できるようにします。(秒は無視)
1618         *
1619         * @og.rev 3.8.0.7 (2005/09/20) 内部クラスBreakTimeDataを使用するように修正
1620         * @og.rev 3.8.1.6 (2006/04/25) 変数の final 化
1621         * @og.rev 5.6.1.2 (2013/02/22) breakTimesの処理方法の見直し
1622         *
1623         * @og.group 画面部品
1624         *
1625         * @version  4.0
1626         * @author      Kazuhiko Hasegawa
1627         * @since    JDK5.0,
1628         */
1629        private static class BreakTimes {
1630                private final List<BreakTimeData> timeList        = new ArrayList<BreakTimeData>();
1631                private final int               hourOfPixcel    ; // 1時間あたりのピクセル数(例:TIME_PIXEL)
1632                private final String    breakTimeStyle  ; // 休憩時間の指定に追加するスタイル属性
1633                private final int               viewStartTime   ; // 数値化(hm2int)された表示開始時刻(例:0700)
1634                private final int               viewEndTime             ; // 数値化(hm2int)された表示終了時刻(例:2000)
1635
1636                /**
1637                 * コンストラクター
1638                 * 必要な情報を設定して、オブジェクトを構築します。
1639                 * 表示終了時刻は、表示開始時刻 >= 表示終了時刻 の場合、2400加算されている。
1640                 *
1641                 * @og.rev 3.8.0.7 (2005/09/20) breakTimesの日付またがり追加
1642                 * @og.rev 3.8.1.1 (2005/11/21) timeSpan の計算方法を見直し
1643                 * @og.rev 5.6.1.2 (2013/02/22) breakTimesの処理方法の見直し
1644                 *
1645                 * @param       hOfpx   1時間あたりのピクセル数
1646                 * @param       breakTimes      休憩時間を、HHmm-HHmm形式、または、yyyyMMddHHmm-HHmm、または、yyyyMMddHHmm-yyyyMMddHHmm形式で指定します。
1647                 * @param       style   休憩時間の指定に追加するスタイル属性
1648                 * @param       vStartTime      数値化(hm2int)された表示開始時刻
1649                 * @param       vEndTime        数値化(hm2int)された表示終了時刻
1650                 */
1651                BreakTimes( final int hOfpx,final String breakTimes,final String style,
1652                                        final int vStartTime,final int vEndTime ) {
1653                        hourOfPixcel    = hOfpx;
1654                        breakTimeStyle  = ( style == null ) ? "" : style ;
1655                        viewStartTime   = vStartTime;
1656                        viewEndTime             = vEndTime;
1657                        boolean time24          = ( viewEndTime > 2400 );    // 3.8.1.1 (2005/11/21) 開始終了が逆転している場合 true
1658
1659                        // 3.8.1.1 (2005/11/21) timeSpan の計算方法を見直し
1660                        DateFormat format = new SimpleDateFormat( "yyyyMMdd",Locale.JAPAN );
1661                        String[] startEnds = StringUtil.csv2Array( breakTimes );
1662                        int len = startEnds.length;
1663
1664                        String  startDay        ;               // null の場合は、毎日
1665                        String  endDay          ;               // 一時変数
1666                        int             startTime       ;               // 開始時刻のhm2int変換済み値
1667                        int             endTime         ;               // 終了時刻のhm2int変換済み値
1668                        int             timeSpan        ;               // 開始時刻と終了時刻の時間差(hm2int変換済み値)
1669                        String  viewTime        ;               // ツールチップ表示用の文字列(HH:mm-HH:mm)
1670
1671                        Calendar str ;
1672                        Calendar end ;
1673
1674                        for( int i=0; i<len; i++ ) {
1675                                String startEnd = startEnds[i];
1676                                if( startEnd != null ) {
1677                                        // startEnd     = "0700ss-2000ss";                                              // 開始-終了時刻(HHmm-HHmm)
1678                                        // startEnd     = "200508200700ss-2000ss";                              // 開始-終了時刻(yyyyMMddHHmm-HHmm)
1679                                        // startEnd     = "200508200700ss-200508212000ss";              // 開始-終了時刻(yyyyMMddHHmm-yyyyMMddHHmm)
1680
1681                                        // 5.6.1.2 (2013/02/22) breakTimesの処理方法の見直し
1682                                        int idx = startEnd.indexOf( '-' );      // ハイフンを見つける。
1683                                        if( idx > 0 ) {
1684                                                String st = startEnd.substring( 0,idx );
1685                                                String ed = startEnd.substring( idx+1 );
1686
1687                                                startDay        = (st.length() >= 8) ? st.substring( 0,8 ) : null ;          // 8ケタ以上で、yyyyMMdd 取得
1688                                                endDay          = (ed.length() >= 8) ? ed.substring( 0,8 ) : null ;          // 8ケタ以上で、yyyyMMdd 取得
1689                                                startTime       = hm2int( st );
1690                                                endTime         = hm2int( ed );
1691                                        }
1692                                        // startEnd     = "0700ss";                                             // 開始時刻(HHmm)
1693                                        // startEnd     = "200508200700ss";                             // 開始時刻(yyyyMMddHHmm)
1694                                        // startEnd     = "200508200700ss";                             // 開始時刻(yyyyMMddHHmm)
1695                                        else {
1696                                                String st = startEnd;
1697                                                startDay        = (st.length() >= 8) ? st.substring( 0,8 ) : null ;          // 8ケタ以上で、yyyyMMdd 取得
1698                                                endDay          = null ;
1699                                                startTime       = hm2int( st );
1700                                                endTime         = startTime + 1;                                                                                // 差分を出すため、startTime に 1 だけ加算
1701                                        }
1702
1703                                        // 5.6.1.2 (2013/02/22) 処理見直し
1704//                                      // startEnd     = "0700-2000";  // 開始-終了時刻(HHmm-HHmm)
1705//                                      if( startEnd.length() == 9 && startEnd.charAt(4) == '-' ) {
1706//                                              startDay        = null;
1707//                                              endDay          = null;
1708//                                              startTime       = ym2int( startEnd.substring( 0,2 ),startEnd.substring( 2,4 ) );
1709//                                              endTime         = ym2int( startEnd.substring( 5,7 ),startEnd.substring( 7 ) );
1710//                                      }
1711//                                      // startEnd     = "200508200700-2000";  // 開始-終了時刻(yyyyMMddHHmm-HHmm)
1712//                                      else if( startEnd.length() == 17 && startEnd.charAt(12) == '-' ) {
1713//                                              startDay        = startEnd.substring( 0,8 );
1714//                                              endDay          = null;
1715//                                              startTime       = ym2int( startEnd.substring( 8,10  ),startEnd.substring( 10,12 ) );
1716//                                              endTime         = ym2int( startEnd.substring( 13,15 ),startEnd.substring( 15 ) );
1717//                                      }
1718//                                      // startEnd     = "200508200700-200508212000";  // 開始-終了時刻(yyyyMMddHHmm-yyyyMMddHHmm)
1719//                                      else if( startEnd.length() == 25 && startEnd.charAt(12) == '-' ) {
1720//                                              startDay        = startEnd.substring( 0,8 );
1721//                                              endDay          = startEnd.substring( 13,21 );
1722//                                              startTime       = ym2int( startEnd.substring( 8,10  ),startEnd.substring( 10,12 ) );
1723//                                              endTime         = ym2int( startEnd.substring( 21,23 ),startEnd.substring( 23 ) );
1724//                                      }
1725//                                      else {
1726//                                              String errMsg = "休憩時間は、HHmm-HHmm形式、または、yyyyMMddHHmm-HHmm、または、yyyyMMddHHmm-yyyyMMddHHmm形式です。"
1727//                                                                      + HybsSystem.CR
1728//                                                                      + "breakTimes=[" + breakTimes + "] Bad=[" + startEnd + "]" ;
1729//                                              throw new HybsSystemException( errMsg );
1730//                                      }
1731
1732                                        str = null;
1733                                        end = null;
1734                                        if( startDay != null ) { str = HybsSystem.getCalendar( startDay ); }
1735                                        if( endDay   != null ) { end = HybsSystem.getCalendar( endDay   ); }
1736
1737                                        // 表示終了時刻 が 2400 より大きい場合、表示開始時刻 >= 表示終了時刻 である。
1738                                        if( time24 ) {
1739                                                // 開始時刻 <  表示終了時刻 => 開始時刻に2400加算する。
1740                                                if( startTime < viewEndTime-2400 ) {
1741                                                        if( str != null ) {
1742                                                                str.add(Calendar.DATE, -1 );    // -1 日しておく
1743                                                                startDay = format.format( str.getTime() );
1744                                                        }
1745                                                        startTime += 2400;
1746                                                }
1747
1748                                                // 終了時刻 <= 表示終了時刻 => 終了時刻に2400加算する。
1749                                                if( endTime <= viewEndTime-2400 ) {
1750                                                        if( end != null ) {
1751                                                                end.add(Calendar.DATE, -1 );    // -1 日しておく
1752                                                                endDay = format.format( end.getTime() );
1753                                                        }
1754                                                        endTime += 2400;
1755                                                }
1756                                        }
1757
1758                                        // 3.8.1.1 (2005/11/21) 判定条件修正
1759                                        // 開始時刻 < 表示開始時刻 => 開始時刻に表示開始時刻をセット。
1760                                        if( startTime < viewStartTime ) { startTime = viewStartTime; }
1761
1762                                        // 開始時刻 > 表示終了時刻 => 開始時刻に表示終了時刻をセット。
1763                                        if( startTime > viewEndTime ) { startTime = viewEndTime; }
1764
1765                                        // 終了時刻 < 表示開始時刻 => 終了時刻に表示開始時刻をセット。
1766                                        if( endTime < viewStartTime ) { endTime = viewStartTime; }
1767
1768                                        // 終了時刻 > 表示終了時刻 => 終了時刻に表示終了時刻をセット。
1769                                        if( endTime > viewEndTime ) { endTime = viewEndTime; }
1770                                        timeSpan = endTime - startTime ;
1771                                        viewTime = startEnd ;
1772                                }
1773                                // null の場合は、カンマが連続したり、最後に余分に付いたケースなので、無視する。
1774                                else {
1775                                        continue;
1776                                }
1777
1778                                // 終了日が入っていないか、開始日と終了日が同じ日の場合。
1779                                if( timeSpan >= 0 && (
1780                                        endDay == null || ( startDay != null && startDay.equals( endDay ) ) ) ) {
1781                                                timeSpan = endTime - startTime ;
1782                                                timeList.add( new BreakTimeData( startDay,startTime,timeSpan,viewTime ) );
1783                                }
1784                                else {
1785                                        // 終了日が入っていると複数日に分かれているので、分解する必要がある。
1786
1787                                        // 初日の timeSpan は、startTime から viewEndTime まで
1788                                        timeSpan = viewEndTime - startTime ;
1789                                        timeList.add( new BreakTimeData( startDay,startTime,timeSpan,viewTime ) );
1790
1791                                        // 最終日の timeSpan は、viewStartTime から endTime まで
1792                                        timeSpan = endTime - viewStartTime ;
1793                                        timeList.add( new BreakTimeData( endDay,viewStartTime,timeSpan,viewTime ) );
1794
1795                                        // 中日の timeSpan は、viewStartTime から viewEndTime まで
1796                                        timeSpan = viewEndTime - viewStartTime ;
1797                                        if( str != null && end != null ) {
1798                                                str.add(Calendar.DATE, 1 );             // +1 日しておく
1799                                                while( str.before( end ) ) {    // 終了時間は、「含まない」仕様
1800                                                        Date dt = str.getTime();
1801                                                        String tempStartDay = format.format( dt );
1802                                                        timeList.add( new BreakTimeData( tempStartDay,viewStartTime,timeSpan,viewTime ) );
1803                                                        str.add(Calendar.DATE, 1);
1804                                                }
1805                                        }
1806                                }
1807                        }
1808                }
1809
1810                /**
1811                 * その日のその時間の休憩時間を表す SPANタグ群(複数ありうる)を作成します。
1812                 *
1813                 * @og.rev 3.8.9.2 (2007/07/28) 時間間隔パラメータ追加
1814                 *
1815                 * @param       offset  表示開始ピクセル数(実質表示日数 * 1日分のピクセル - オフセット)
1816                 * @param day Calendar 処理すべき日付のカレンダ
1817                 * @param       time    処理すべき時間
1818                 * @param       step    時間間隔
1819                 * @return その日のその時間の休憩時間を表す SPANタグ群(複数ありうる)
1820                 */
1821//              String makeSpan( final int offset,final Calendar day,final int time ) {
1822                String makeSpan( final int offset,final Calendar day,final int time,final int step ) {
1823                        DateFormat format1 = new SimpleDateFormat( "yyyyMMdd",Locale.JAPAN );
1824                        String inDay = format1.format( day.getTime() );
1825
1826                        StringBuilder buf = new StringBuilder();
1827                        int size = timeList.size();
1828                        for( int i=0; i<size; i++ ) {
1829                                BreakTimeData timeData = timeList.get(i);
1830//                              if( timeData.startsWith( inDay,time ) ) {
1831                                if( timeData.startsWith( inDay,time,step ) ) {
1832                                        buf.append( timeData.getBreakTime( offset,hourOfPixcel,breakTimeStyle ) );
1833                                }
1834                        }
1835
1836                        String rtn = null;
1837
1838                        if( buf.length() > 0 ) { rtn = buf.toString(); }
1839                        return rtn;
1840                }
1841        }
1842
1843        /**
1844         * このオブジェクトの文字列表現を返します。
1845         * 基本的にデバッグ目的に使用します。
1846         *
1847         * @return このクラスの文字列表現
1848         */
1849        @Override
1850        public String toString() {
1851                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
1852                                .println( "VERSION"                     ,VERSION                )
1853                                .println( "startDate"           ,startDate              )
1854                                .println( "endDate"                     ,endDate                )
1855                                .println( "daySpan"                     ,daySpan                )
1856                                .println( "zoom"                        ,zoom                   )
1857                                .println( "breakTimes"          ,breakTimes             )
1858                                .println( "breakTimeStyle"      ,breakTimeStyle )
1859                                .println( "baseTimes"           ,baseTimes              )               // 5.6.1.2 (2013/02/22) ベース時刻
1860                                .println( "baseTimeStyle"       ,baseTimeStyle  )               // 5.6.1.2 (2013/02/22) ベース時刻スタイル
1861                                .println( "calDB"                       ,calDB                  )
1862                                .println( "arg1"                        ,arg1                   )
1863                                .println( "arg2"                        ,arg2                   )
1864                                .println( "arg3"                        ,arg3                   )
1865                                .println( "arg4"                        ,arg4                   )
1866                                .println( "skipHoliday"         ,skipHoliday    )
1867                                .println( "TIME_PIXEL"          ,TIME_PIXEL     )
1868                                .println( "Other..."            ,getAttributes().getAttribute() )
1869                                .fixForm().toString() ;
1870        }
1871}