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     */
016    package org.opengion.fukurou.util;
017    
018    import java.util.Arrays;
019    import java.util.Calendar;
020    import java.util.Date;
021    import java.util.Locale;
022    import java.util.Map;
023    import java.util.HashMap;
024    import java.text.DateFormat;
025    import java.text.SimpleDateFormat;
026    import java.text.ParseException;
027    
028    /**
029     * HybsDateUtil.java は、å?通的に使用されã‚?Date,Calender関連メソãƒ?ƒ‰を集ç´?�—たã?staticメソãƒ?ƒ‰のみで構æ?されるクラスですã?
030     *
031     * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
032     *
033     * @og.group ユーãƒ?‚£リãƒ?‚£
034     *
035     * @version  5.5
036     * @author       Kazuhiko Hasegawa
037     * @since    JDK7.0,
038     */
039    public final class HybsDateUtil {
040    
041            /** シスãƒ?ƒ 依存ã?改行記号をセãƒ?ƒˆしますã?     */
042            private static final String CR = System.getProperty("line.separator");
043    
044            /** å�?¨®フォーマットを簡易的に表したæ–?­—å? */
045            private static final Map<String,String>   DATE_FORMAT = new HashMap<String,String>();
046            static {
047                    DATE_FORMAT.put( "YMD"          ,"yyyyMMdd"                             );
048                    DATE_FORMAT.put( "Y2MD"         ,"yyMMdd"                               );
049                    DATE_FORMAT.put( "YM"           ,"yyyyMM"                               );
050                    DATE_FORMAT.put( "MD"           ,"MMdd"                                 );      // 5.5.5.2 (2012/08/18)
051                    DATE_FORMAT.put( "HMS"          ,"HHmmss"                               );
052                    DATE_FORMAT.put( "YMDHMS"       ,"yyyyMMddHHmmss"               );
053                    DATE_FORMAT.put( "EEE"          ,"EEE"                                  );
054                    DATE_FORMAT.put( "YMDF"         ,"yyyy/MM/dd"                   );
055                    DATE_FORMAT.put( "Y2MDF"        ,"yy/MM/dd"                     );
056                    DATE_FORMAT.put( "YMF"          ,"yyyy/MM"                              );
057                    DATE_FORMAT.put( "HMSF"         ,"HH:mm:ss"                     );
058                    DATE_FORMAT.put( "YMDHMSF"      ,"yyyy/MM/dd HH:mm:ss"  );
059                    DATE_FORMAT.put( "MDF"          ,"MM/dd"                                ); // 5.5.0.2 (2012/03/09) 和暦
060                    DATE_FORMAT.put( "MDEF"         ,"MM/dd(EEE)"                   ); // 5.5.0.2 (2012/03/09) 和暦
061                    DATE_FORMAT.put( "MD2F"         ,"MMæœ?d日"                              ); //                                                           5.5.5.2 (2012/08/18) 和暦
062                    DATE_FORMAT.put( "GYMDF"        ,"GGGGyyyy年MMæœ?d日"    ); // 5.5.0.2 (2012/03/09) 和暦
063                    DATE_FORMAT.put( "G2YMDF"       ,"Gyyyy/MM/dd"                  ); // 5.5.0.2 (2012/03/09) 和暦
064                    DATE_FORMAT.put( "GYMF"         ,"GGGGyyyy年MMæœ?                ); // 5.5.0.2 (2012/03/09) 和暦
065                    DATE_FORMAT.put( "GYF"          ,"GGGGyyyy"                     ); // 5.5.0.2 (2012/03/09) 和暦
066            }
067    
068            /**
069             *      ãƒ?ƒ•ォルトコンストラクターをprivateにしてã€?
070             *      オブジェクトã?生æ?をさせなã�?‚ˆã�?�«するã€?
071             *
072             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
073             *
074             */
075            private HybsDateUtil() {}
076    
077            /**
078             * 現在日付ã?時刻を指定ã?フォーマットでæ–?­—å?に変換して返しますã?
079             * 出力フォーマットã?ã€?yyyy/MM/dd HH:mm:ss" 固定ですã?
080             *
081             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
082             *
083             * @return      現在日付ã?時刻 ( ä¾?2012/09/05 18:10:24 )
084             */
085            public static final String getDate() {
086                    DateFormat formatter = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss",Locale.JAPAN );
087                    return formatter.format(new Date());
088            }
089    
090            /**
091             * 現在時刻を指定ã?フォーマットでæ–?­—å?に変換して返しますã?
092             * フォーマットã?æŒ?®š方法ã?、java.text.SimpleDateFormat のæŒ?®š方法と同ä¸?�§すã?
093             * 変換時ã?ロケーションは、Locale.JAPAN ですã?
094             * 現在時刻は、new Date() で求めますã?
095             *
096             * @param       form フォーãƒ?–‡字å? ( ä¾?"yyyy/MM/dd HH:mm:ss.SSS" )
097             *
098             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
099             *
100             * @return      現在日付ã?時刻
101             * @see         java.text.SimpleDateFormat
102             */
103            public static final String getDate( final String form ) {
104                    DateFormat formatter = new SimpleDateFormat( form,Locale.JAPAN );
105                    return formatter.format( new Date() );
106            }
107    
108            /**
109             * æŒ?®š時刻を指定ã?フォーマットでæ–?­—å?に変換して返しますã?
110             * フォーマットã?æŒ?®š方法ã?、java.text.SimpleDateFormat のæŒ?®š方法と同ä¸?�§すã?
111             * 変換時ã?ロケーションは、Locale.JAPAN ですã?
112             * æŒ?®š時刻は、new Date( time ) で求めますã?
113             *
114             * @param       time æŒ?®šã?カレントタイãƒ??ロング値
115             * @param       form フォーãƒ?–‡字å? ( ä¾?"yyyy/MM/dd HH:mm:ss.SSS" )
116             *
117             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
118             *
119             * @return      現在日付ã?時刻( ä¾?2001/04/17 15:48:22 )
120             */
121            public static final String getDate( final long time,final String form ) {
122                    DateFormat formatter = new SimpleDateFormat( form,Locale.JAPAN );
123                    return formatter.format( new Date( time ) );
124            }
125    
126            /**
127             * æŒ?®šã?æ–?­—å?から、以下ã?æ–?­—を削除したæ–?­—å?を返しますã?
128             * '/' , '-' , ' ' , ':' の数字以外ã?æ–?­—を含ã‚?ƒ•ォーマットされた
129             * 日付文字å?をã?日付データã�?�‘に変換する場合に利用することを想定してã�?�¾すã?
130             * よって、ã?イナス記号ã‚??小数点、コンマなども削除されますã?
131             * こã?メソãƒ?ƒ‰では、日付としての整合æ?ã‚?¡�チェãƒ?‚¯は行いませんã€?
132             * 
133             * 引数がã?null の場合ã?、ゼロæ–?­—å?に、変換しますã?
134             *
135             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
136             * @og.rev 5.5.8.3 (2012/11/17) 数字ã?み返す仕様だったが、対象以外ã?æ–?­—å?力ã?そã?まま返すよう変更
137             *
138             * @param       value 任意ã?æ–?­—å??ˆ例ï¼?001/04/17 15:48:22??
139             *
140             * @return      数字だけで構æ?される文字å??ˆ例ï¼?0010417154822??nullはゼロæ–?­—å?を返しまã�?
141             */
142            public static final String parseNumber( final String value ) {
143                    if( value == null ) { return ""; }
144    
145                    StringBuilder buf = new StringBuilder();
146                    for( int i=0; i<value.length(); i++ ) {
147                            char ch = value.charAt(i);
148    //                      if( ch >= '0' && ch <= '9' ) { buf.append( ch ); }
149                            if( ch == '/' || ch == '-' || ch == ' ' || ch == ':'){} // 5.5.8.3 (2012/11/17) 何もしなã�?
150                            else {
151                                    buf.append( ch );
152                            }
153                    }
154    
155                    return buf.toString();
156            }
157    
158            /**
159             * æŒ?®šã?æ–?­—å?から、yyyy-mm-dd hh:mm:ss[.f...] 形式ã?æ–?­—å?を作æ?しますã?
160             * これは、java.sql.Timestamp オブジェクトをæ–?­—å?から作æ?するに当たりã?
161             * Timestamp のæ–?­—å?形式にしなければならなã�?�Ÿめですã?
162             * 桁数はã€?¼˜æ¡?またã?ã€?¼‘4桁以外ã?場合ã?、変換エラーとしますã?
163             *
164             * @og.rev 5.5.8.5 (2012/11/27) 新規作æ?
165             *
166             * @param       value 任意ã?æ–?­—å??ˆ例ï¼?0010417 or 20010417154822??
167             *
168             * @return      Timestampのæ–?­—å?形式(例ï¼?001-04-17 00:00:00 or 2001-04-17 15:48:22??
169             */
170            public static final String parseTimestamp( final String value ) {
171                    if( value == null || ( value.length() != 8 && value.length() != 14 ) ) {
172                            String errMsg = "日付文字å?に、不正な値が指定されました。8æ¡?またã?ã€?¼‘4桁でæŒ?®šしてくださいã€?
173                                                    + " value=[" + value + "]" ;
174                            throw new RuntimeException( errMsg );
175                    }
176    
177                    StringBuilder buf = new StringBuilder();
178                    buf.append( value.substring( 0,4 ) ).append( "-" );
179                    buf.append( value.substring( 4,6 ) ).append( "-" );
180                    buf.append( value.substring( 6,8 ) ).append( " " );
181                    if( value.length() == 8 ) {
182                            buf.append( "00:00:00" );
183                    }
184                    else {
185                            buf.append( value.substring( 8,10  ) ).append( ":" );
186                            buf.append( value.substring( 10,12 ) ).append( ":" );
187                            buf.append( value.substring( 12,14 ) );
188                    }
189    
190                    return buf.toString();
191            }
192    
193            /**
194             * 日付文字å?の桁数の整合æ?を取りますã?
195             * これは、å?部で、parseNumber(String) 処ç�?�«より、不要なフォーマット記号を削除しますã?
196             * ここでは、基本çš?�«はã€?¼–文字ï¼?yyyMM?‰ã??˜文字ï¼?yyyMMdd?‰ã??‘4文字ï¼?yyyMMddHHmmss??
197             * の日付文字å?を作æ?することを想定してã�?�¾すが、指定ã?桁数以外ã?、エラーになりますã?
198             * 
199             * 引数がã?null         â‡?桁数に無関係に、空æ–?­—å?を返すã€?
200             * 引数の桁数がä¸??     â‡?そã?値を返すã€?
201             * 引数の桁数が不ä¸??   â‡?エラー
202             * ただしã?引数のæœ?¤§長はã€?¼‘4ケタに制限してã�?�¾すã?
203             * 
204             * こã?メソãƒ?ƒ‰では、日付として成立してã�?‚‹かどã�?�‹??9999999など?‰ã?判定してã�?�¾せんã€?
205             *
206             * @og.rev 5.6.6.0 (2013/07/05) メソãƒ?ƒ‰のå†?®¹を移すã?
207             *
208             * @param       value   任意ã?日付けæ–?­—å?
209             * @param       size    変換したã�?¡�数
210             *
211             * @return      数字だけで構æ?される文字å??ˆ例ï¼?0010417154822??nullはゼロæ–?­—å?を返しまã�?
212             */
213            public static final String parseDate( final String value , final int size ) {
214                    return parseDate( value , size , size );                // æœ?°�とæœ?¤§を同じå?にするã€?
215            }
216    
217            /**
218             * 日付文字å?の桁数の整合æ?を取りますã?
219             * これは、å?部で、parseNumber(String) 処ç�?�«より、不要なフォーマット記号を削除しますã?
220             * ここでは、基本çš?�«はã€?¼–文字ï¼?yyyMM?‰ã??˜文字ï¼?yyyMMdd?‰ã??‘4文字ï¼?yyyMMddHHmmss??
221             * の日付文字å?を作æ?することを想定してã�?�¾すが、それ以外ã?桁数でも下記ã?ルールに従って
222             * 処ç�?�•れますã?
223             * 
224             * 引数がã?null         â‡?桁数に無関係に、空æ–?­—å?を返すã€?
225             * 引数の桁数がç¯?›²å†?  â‡?以下ã?処ç�?‚’実行するã?
226             * 引数の桁数を同ã�?    â‡?そã?まま返すã€?
227             * 引数の桁数より大きい â‡?余をカãƒ?ƒˆして、引数のæœ?¤§長にそろえるã€?
228             * 引数の桁数に足りなã�?â‡?"20000101000000" のæ–?­—å?の部åˆ?–‡字å?を結合させて、引数のæœ?¤§長にそろえるã€?
229             * ただしã?引数のæœ?¤§長はã€?¼‘4ケタに制限してã�?�¾すã?
230             * 
231             * こã?メソãƒ?ƒ‰では、日付として成立してã�?‚‹かどã�?�‹??9999999など?‰ã?判定してã�?�¾せんã€?
232             *
233             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
234             * @og.rev 5.6.1.1 (2013/02/08) 桁数チェãƒ?‚¯導å?。6桁以下だとエラーにするã€?
235             * @og.rev 5.6.6.0 (2013/07/05) 桁数チェãƒ?‚¯のæœ?°?æœ?¤§æŒ?®?
236             *
237             * @param       value   任意ã?日付けæ–?­—å?
238             * @param       minSize 変換したã�?¡�数のæœ?°�å?
239             * @param       maxSize 変換したã�?¡�数のæœ?¤§値
240             *
241             * @return      数字だけで構æ?される文字å??ˆ例ï¼?0010417154822??nullはゼロæ–?­—å?を返しまã�?
242             */
243    //      public static final String parseDate( final String value , final int size ) {
244            public static final String parseDate( final String value , final int minSize , final int maxSize ) {
245                    if( value == null ) { return ""; }
246    
247                    String rtn = parseNumber( value );
248    
249                    // 引数のæœ?¤§長はã€?¼‘4ケタに制限してã�?�¾すã?
250                    if( maxSize > 14 ) {
251                            String errMsg = "日付登録に許可できるæœ?¤§桁数はã€?¼‘4ケタですã?"
252                                                    + " maxSize=[" + maxSize + "]" ;
253                            throw new RuntimeException( errMsg );
254                    }
255    
256    //              int maxSize = ( size > 14 ) ? 14 : size ;            // 先にæœ?¤§サイズを求めておく
257                    int len     = rtn.length() ;
258    
259                    if(      len == maxSize ) { rtn = value; }
260    //              else if( len >  maxSize ) { rtn = rtn.substring( 0,maxSize ); }
261                    // 5.6.1.1 (2013/02/08) 桁数チェãƒ?‚¯導å?。6桁以下だとエラーにするã€?
262    //              else if( len < 6 ) {
263                    // 5.6.6.0 (2013/07/05) 桁数チェãƒ?‚¯のæœ?°?æœ?¤§æŒ?®šで、ç¯?›²外ã?エラー
264                    else if( len < minSize || len > maxSize ) {
265                            String errMsg = "日付文字å?に、不正な値が指定されました。最小["
266                                                    + minSize + "] から、最大[" + maxSize + "]のç¯?›²でæŒ?®šしてくださいã€?
267                                                    + " value=[" + value + "]" ;
268                            throw new RuntimeException( errMsg );
269                    }
270                    else {
271                            rtn = rtn + "20000101000000".substring( len,maxSize ) ; // 中間文字å?を加えるã€?
272                    }
273    
274                    return rtn ;
275            }
276    
277            /**
278             * 日付文字å?の厳å¯?�ª整合æ?チェãƒ?‚¯を行いますã?
279             * ここでæŒ?®šできるのはã€?¼˜文字ï¼?yyyMMdd?‰ã??‘4文字ï¼?yyyMMddHHmmss?‰ã?どちらかの
280             * 数字だけã?日付文字å?であり、それが、日付として正しいかどã�?�‹のチェãƒ?‚¯を行いますã?
281             * 正しけれã?、true をã?間違ってã�?‚Œば、false を返しますã?
282             * ここではã€?0120230?ˆ2月?“0日?‰などの日付やã€?0120101235960 などã‚?false になりますã?
283             * 引数がã?null および、空æ–?­—å?の場合も、false を返しますã?でã€?�¿けたã�??合ã?、事前に
284             * 判定しておいてくださいã€?
285             *
286             * å†?ƒ¨処ç�?�¨しては、DateFormat で、setLenient( false ) を設定することでã€?
287             * 日ä»?時刻解析を厳å¯?�«解析するにして、ParseException が発生しなã�?�‹どã�?�‹判定してã�?�¾すã?
288             *
289             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
290             *
291             * @param       value  数字だけで構æ?される日付けæ–?­—å?
292             *
293             * @return      true:日付として正しい場å�?false:日付として間違ってã�?‚‹場å�?
294             */
295            public static final boolean isStrict( final String value ) {
296                    if( value == null || ( value.length() != 8 && value.length() != 14 ) ) { return false; }
297    
298                    // 日付ã?厳å¯?�ªチェãƒ?‚¯
299                    String form = (value.length() == 8) ? "yyyyMMdd" : "yyyyMMddHHmmss" ;
300                    DateFormat formatter = new SimpleDateFormat( form,Locale.JAPAN );
301                    formatter.setLenient( false );          // 日ä»?時刻解析を厳å¯?�«行う(false=厳å¯?
302    
303                    boolean flag ;
304                    try {
305                            formatter.parse( value );
306                            flag = true;
307                    }
308                    catch( ParseException ex ) {
309                            flag = false;
310                    }
311    
312                    return flag;
313            }
314    
315            /**
316             * 日付関係ã?æƒ??を簡易的に処ç�?�—ますã?
317             *
318             * CC引数のåŠ?¸›算パラメータはã€? ですã?
319             *
320             * @og.rev 5.7.4.1 (2014/03/14) CC 引数を拡張するため、旧メソãƒ?ƒ‰をå?現しておきますã?
321             *
322             * @param   key         フォーマットã?予ç´?ª?
323             * @param   prmA        基準となる日ä»?nullの場合ã?、å?ç�?™‚刻)
324             * @param   prmB        処ç�?‚³マンãƒ?
325             *
326             * @return   メãƒ?‚»ージæƒ??
327             * @see         #getDateFormat( String , String ,String , int )
328             */
329            public static final String getDateFormat( final String key ,final String prmA ,final String prmB ) {
330                    return getDateFormat( key,prmA,prmB,0 );
331            }
332    
333            /**
334             * 日付関係ã?æƒ??を簡易的に処ç�?�—ますã?
335             *
336             * 第ä¸?¼•数 "XXXX" は、日付å?ç�?‚’行うフォーマットã?予ç´?ªžになってã�?�¾すã?
337             * ・YMDã€???š8文字ã?4-2-2年月日ãƒ??タ(yyyyMMdd)を扱ã�?�¾すã?
338             * ・Y2MDã€??š6文字ã?2-2-2年月日ãƒ??タ(yyMMdd)を扱ã�?�¾すã?
339             * ・YMã€?? ?š6文字ã?4-2年月データ(yyyyMM)を扱ã�?�¾すã?
340             * ・HMSã€???š6文字ã?2-2-2時å?秒データ(HHmmss)を扱ã�?�¾すã?
341             * ・YMDHMS ?š14文字ã?4-2-2-2-2-2年月日時å?秒データ(yyyyMMddHHmmss)を扱ã�?�¾すã?
342             * ・EEEã€???š曜日をデフォルトロケールで表示しますã?
343             *
344             * F付きは、フォーマットされた日付を返しますã?
345             * ・YMDFã€??š10文字ã?日付表現(yyyy/MM/dd)を扱ã�?�¾すã?
346             * ・Y2MDFã€?¼š8文字ã?日付表現(yy/MM/dd)を扱ã�?�¾すã?
347             * ・YMFã€???š7文字ã?日付表現(yyyy/MM)を扱ã�?�¾すã?
348             * ・HMSFã€??š8文字ã?時刻表現(HH:mm:ss)を扱ã�?�¾すã?
349             * ・YMDHMSF?š19文字ã?日付表現(yyyy/MM/dd HH:mm:ss)を扱ã�?�¾すã?
350             * ・MDFã€???š5文字ã?月日表現(MM/dd)を扱ã�?�¾すã?
351             * ・MDEFã€??š5文字+曜日の月日表現(MM/dd(EEE))を扱ã�?�¾すã?
352             * ・MD2Fã€??š和暦の月日表現(MMæœ?d日)を扱ã�?�¾すã?(5.5.5.2 追åŠ?
353             * ・GYMDFã€?¼š和暦の年月日表現(GGGGyyyy年MMæœ?d日)を扱ã�?�¾すã?
354             * ・G2YMDF ?š和暦の日付表現(Gyyyy/MM/dd)を扱ã�?�¾すã?
355             * ・GYMFã€??š和暦の年月表現(GGGGyyyy年MMæœ?を扱ã�?�¾すã?
356             * ・GYFã€???š和暦の年表現(GGGGyyyy)を扱ã�?�¾すã?
357             *
358             * なおã?上記以外ã?フォーマットをæŒ?®šするå?合ã?、XXXX部åˆ?�«直接記述できますã?(5.5.5.2 追åŠ?
359             * ただしã?基本çš?�«は、è?由フォーマットã?、エラーチェãƒ?‚¯がなã�?‚º、使わなã�?�§くださいã€?
360             *
361             * 第二引数 AA は、基準となる日付を、yyyyMMdd形式でæŒ?®šしますã?nullの場合ã?、現在時刻を使用しますã?
362             * æŒ?®šできる日付ã?、yyyyMMdd形式を推奨しますがã€?/' , '-' , ' ' , ':' を削除して使ã�?�¾すã?
363             * ?–桁ã?場合ã?、yyyyMM + 01 としã??˜ケタの場合ã?、yyyyMMdd としã?14ケタ以上ã?場合ã?、前半14文字を
364             * yyyyMMddHHmmss として処ç�?�—ますã?それ以外ã?桁数の場合ã?、エラーになりますã?
365             * たとえã?ã€?2012/09/05 16:52:36" のようなフォーマットデータの場合ã?'/' , '-' , ' ' , ':' を削除して
366             * "20120905165236" に変換後ã?日付オブジェクトに変換されますã?
367             *
368             * 第三引数 BB は、日付につã�?�¦のåŠ?¸›算å?ç�?‚’行うためのコマンドをæŒ?®šしますã?
369             * nullの場合ã?、なにも加減算å?ç�?‚’行いませんã€?
370             * ・SD ?š当月のæœ??の日付にセãƒ?ƒˆしますã?(当月?‘日)ã€?C引数はã€?N:N月前ã€?:当月(=SD)、N:N月後ã?-1:BSD と同じã€?:ASD と同じ
371             * ・ED ?š当月のæœ?¾Œã?日付にセãƒ?ƒˆしますã?(当月月末)ã€?C引数はã€?N:N月前ã€?:当月(=ED)、N:N月後ã?-1:BED と同じã€?:AED と同じ
372             * ・SW ?š日付å?ç�??週初め(月曜日)にセãƒ?ƒˆしますã?日付ã?当日より前に移動しますã?CC引数はã€?N:N週前ã?0:今é?(=SW)、N:N週å¾?
373             * ・EW ?š日付å?ç�??週末(日曜日)にセãƒ?ƒˆしますã?日付ã?当日より後ろに移動しますã?CC引数はã€?N:N週前ã?0:今é?(=EW)、N:N週å¾?
374             * ・H1 ??HXXX ?š時を指定ã?åˆ?� けé?めますã?H1なら1時間後ã?H24 なら24時間å¾?5.5.5.6 (2012/08/31) 追åŠ?
375             * ・D1 ??DXXX ?š日を指定ã?åˆ?� けé?めますã?D1なら翌日、D200 なã‚?00日å¾?
376             * ・M1 ??MXXX ?š月を指定ã?åˆ?� けé?めますã?M1なら翌月、M6 なら半年å¾?
377             * ・BSD ??有閑)先月のæœ??の日付にセãƒ?ƒˆしますã?(先月?‘日)(5.5.5.2 追åŠ?。SD -1 と同ç­?
378             * ・BED ??有閑)先月のæœ?¾Œã?日付にセãƒ?ƒˆしますã?(先月月末)(5.5.5.2 追åŠ?ã€?D -1 と同ç­?
379             * ・ASD ??有閑)翌月のæœ??の日付にセãƒ?ƒˆしますã?(翌月?‘日)(5.5.5.2 追åŠ?。SD 1  と同ç­?
380             * ・AED ??有閑)翌月のæœ?¾Œã?日付にセãƒ?ƒˆしますã?(翌月月末)(5.5.5.2 追åŠ?ã€?D 1  と同ç­?
381             *
382             * CC 引数は、特別な処ç�?�§、BB 引数に対して、加算ã?減算ã?ための数字をæŒ?®šできますã?(5.7.4.1 (2014/03/14) 追åŠ?
383             * 従来は、BB 引数がã?"H" , "D" , "M" の ?‘文字パラメータの場合ã?み利用可能でしたã€?
384             *
385             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
386             * @og.rev 5.6.1.1 (2013/02/08) prmB処ç�?‚’、calendarCalc メソãƒ?ƒ‰へ移å‹?
387             * @og.rev 5.7.4.1 (2014/03/14) CC 引数を拡張
388             *
389             * @param   key         フォーマットã?予ç´?ª?
390             * @param   prmA        基準となる日ä»?nullの場合ã?、å?ç�?™‚刻)
391             * @param   prmB        処ç�?‚³マンãƒ?
392             * @param   intC        åŠ?¸›算å?ç�?‚’行うための数字ã?0 は、BB引数の従来計算ã?ままã€?
393             *
394             * @return   メãƒ?‚»ージæƒ??
395             * @see         #getDateFormat( String , String ,String )
396             * @see         #getCalendar( String )                                          AA 引数 からカレンãƒ?‚ªブジェクトを作æ?しますã?
397             * @see         #calendarCalc( Calendar , String , int )        BB 引数、CC 引数をå?に、日付計算しますã?
398             */
399            public static final String getDateFormat( final String key ,final String prmA ,final String prmB ,final int intC ) {
400    
401                    // prmA ã�?null の場合ã?、そのまま、現在時刻が使われますã?
402                    Calendar now = getCalendar( prmA );
403    
404                    // 5.6.1.1 (2013/02/08) getDateFormat( String ,String ,String ) からåˆ?›¢ã€?
405    //              calendarCalc( now,prmB );
406                    calendarCalc( now,prmB,intC );          // 5.7.4.1 (2014/03/14) CC 引数を拡張
407    
408                    String format = DATE_FORMAT.get( key );
409                    if( format == null ) {
410                            // DATE_FORMAT に存在しなã�?ƒ•ォーマットをæŒ?®šしてもã?エラーにしませんã€?
411                            // ただしã?後å?ç�?�§フォーマットエラーになる可能性は残りますã?
412                            format = key;   // 5.5.5.2 (2012/08/18) 自由フォーマット指å®?
413                    }
414    
415                    //5.5.0.2 先é?Gの場合ã?和暦なのでformatterのLocaleを変更する
416                    DateFormat formatter = null;
417                    if( key.indexOf('G') == 0 ){
418                            formatter = new SimpleDateFormat( format, new Locale("ja","JP","JP"));
419                    }
420                    else{
421                            formatter = new SimpleDateFormat( format,Locale.JAPAN );
422                    }
423    
424                    return formatter.format( now.getTime() );
425            }
426    
427            /**
428             * 開始前設定å?、またã? 終äº?¾Œ設定å?のæ–?­—å?から、オプションæ–?­—å?を合成しますã?
429             * 基準となる日付に計算した結果を反æ˜?�•せますã?
430             *
431             * CC引数のåŠ?¸›算パラメータはã€? ですã?
432             *
433             * @og.rev 5.7.4.1 (2014/03/14) CC 引数を拡張するため、旧メソãƒ?ƒ‰をå?現しておきますã?
434             *
435             * @param   now     基準となる日付ï¼?alendarオブジェクトï¼?
436             * @param   prmB        処ç�?‚³マンãƒ?
437             */
438            public static final void calendarCalc( final Calendar now,final String prmB ) {
439                    calendarCalc( now,prmB,0 );
440            }
441    
442            /**
443             * 開始前設定å?、またã? 終äº?¾Œ設定å?のæ–?­—å?から、オプションæ–?­—å?を合成しますã?
444             * 基準となる日付に計算した結果を反æ˜?�•せますã?
445             *
446             * prmB は、日付につã�?�¦のåŠ?¸›算å?ç�?‚’行うためのコマンドをæŒ?®šしますã?
447             * ・SD ?š当月のæœ??の日付にセãƒ?ƒˆしますã?(当月?‘日)ã€?C引数はã€?N:N月前ã€?:当月(=SD)、N:N月後ã?-1:BSD と同じã€?:ASD と同じ
448             * ・ED ?š当月のæœ?¾Œã?日付にセãƒ?ƒˆしますã?(当月月末)ã€?C引数はã€?N:N月前ã€?:当月(=ED)、N:N月後ã?-1:BED と同じã€?:AED と同じ
449             * ・SW ?š日付å?ç�??週初め(月曜日)にセãƒ?ƒˆしますã?日付ã?当日より前に移動しますã?CC引数はã€?N:N週前ã?0:今é?(=SW)、N:N週å¾?
450             * ・EW ?š日付å?ç�??週末(日曜日)にセãƒ?ƒˆしますã?日付ã?当日より後ろに移動しますã?CC引数はã€?N:N週前ã?0:今é?(=EW)、N:N週å¾?
451             * ・H1 ??HXXX ?š時を指定ã?åˆ?� けé?めますã?H1なら1時間後ã?H24 なら24時間å¾?5.5.5.6 (2012/08/31) 追åŠ?
452             * ・D1 ??DXXX ?š日を指定ã?åˆ?� けé?めますã?D1なら翌日、D200 なã‚?00日å¾?
453             * ・M1 ??MXXX ?š月を指定ã?åˆ?� けé?めますã?M1なら翌月、M6 なら半年å¾?
454             * ・BSD ?šå?月ã?æœ??の日付にセãƒ?ƒˆしますã?(先月?‘日)(5.5.5.2 追åŠ?。SD-1 と同ç­?
455             * ・BED ?šå?月ã?æœ?¾Œã?日付にセãƒ?ƒˆしますã?(先月月末)(5.5.5.2 追åŠ?ã€?D-1 と同ç­?
456             * ・ASD ?š翌月のæœ??の日付にセãƒ?ƒˆしますã?(翌月?‘日)(5.5.5.2 追åŠ?。SD1  と同ç­?
457             * ・AED ?š翌月のæœ?¾Œã?日付にセãƒ?ƒˆしますã?(翌月月末)(5.5.5.2 追åŠ?ã€?D1  と同ç­?
458             * ・数字:日を指定ã?åˆ?� けé?めますã?D1 ??DXXX の簡略系
459             *
460             * CC 引数は、特別な処ç�?�§、BB 引数に対して、加算ã?減算ã?ための数字をæŒ?®šできますã?(5.7.4.1 (2014/03/14) 追åŠ?
461             * HXXX,DXXX,MXXX 形式に、CC 引数を付けたå?合ã?、XXX にさらにåŠ?®—されますã?
462             * prmB に、数字を使用した場合ã?(コマンドでなã�??å�?にもã?CC 引数は、加算されますã?
463             *
464             * @og.rev 5.6.1.1 (2013/02/08) getDateFormat( String ,String ,String ) からåˆ?›¢ã€?
465             * @og.rev 5.7.4.1 (2014/03/14) H1 ??HXXX ?š時を指定ã?åˆ?� けé?める処ç�?�Œ実è£?�•れてã�?�ªかったã?
466             * @og.rev 5.7.4.1 (2014/03/14) CC 引数追åŠ?
467             *
468             * @param   now     基準となる日付ï¼?alendarオブジェクトï¼?
469             * @param   prmB        処ç�?‚³マンãƒ?
470             * @param   intC        åŠ?¸›算å?ç�?‚’行うための数字ã?0 は、BB引数の従来計算ã?ままã€?
471             */
472            public static final void calendarCalc( final Calendar now , final String prmB , final int intC ) {
473    
474                    // 基準ã?、intC == 0 の場å�?
475                    if( prmB != null ) {
476                            if( "SD".equals( prmB ) ) {                                                     // (当月?‘日)
477                                    if( intC != 0 ) { now.add( Calendar.MONTH,intC ); }     // 5.7.4.1 (2014/03/14) CC 引数追åŠ?
478                                    now.set( Calendar.DATE,1 );
479                            }
480                            else if( "ED".equals( prmB ) ) {                                        // (当月月末)
481                                    if( intC != 0 ) { now.add( Calendar.MONTH,intC ); }     // 5.7.4.1 (2014/03/14) CC 引数追åŠ?
482                                    now.set( Calendar.DATE,now.getActualMaximum( Calendar.DATE ) );
483                            }
484                            else if( "BSD".equals( prmB ) ) {                                       // (先月?‘日)
485                                    // 5.7.4.1 (2014/03/14) CC 引数追åŠ?
486                                    now.add( Calendar.MONTH,intC-1 ); now.set( Calendar.DATE,1 );
487    //                              now.roll( Calendar.MONTH,false ); now.set( Calendar.DATE,1 );
488                            }
489                            else if( "BED".equals( prmB ) ) {                                       // (先月月末)
490                                    // 5.7.4.1 (2014/03/14) CC 引数追åŠ?
491                                    now.add( Calendar.MONTH,intC-1 ); now.set( Calendar.DATE,now.getActualMaximum( Calendar.DATE ) );
492    //                              now.roll( Calendar.MONTH,false ); now.set( Calendar.DATE,now.getActualMaximum( Calendar.DATE ) );
493                            }
494                            else if( "ASD".equals( prmB ) ) {                                       // (翌月?‘日)
495                                    // 5.7.4.1 (2014/03/14) CC 引数追åŠ?
496                                    now.add( Calendar.MONTH,intC+1 ); now.set( Calendar.DATE,1 );
497    //                              now.roll( Calendar.MONTH,true );  now.set( Calendar.DATE,1 );
498                            }
499                            else if( "AED".equals( prmB ) ) {                                       // (翌月月末)
500                                    // 5.7.4.1 (2014/03/14) CC 引数追åŠ?
501                                    now.add( Calendar.MONTH,intC+1 ); now.set( Calendar.DATE,now.getActualMaximum( Calendar.DATE ) );
502    //                              now.roll( Calendar.MONTH,true );  now.set( Calendar.DATE,now.getActualMaximum( Calendar.DATE ) );
503                            }
504                            else if( "SW".equals( prmB ) ) {                                        // 週初め(月曜日)セãƒ?ƒˆ
505                                    // 5.7.4.1 (2014/03/14) CC 引数追åŠ?
506                                    if( intC != 0 ) { now.add( Calendar.DATE,intC*7 ); }    // まずã?基準ã?日付を週単位でåŠ?¸›算するã?
507    
508                                    // 日付型æ–?­—å?入力データの開始日を月曜日にセãƒ?ƒˆしますã?
509                                    // SUNDAY=1 , MONDAY=2 になりますã?月曜日との差ã�?�‘、前に戻しますã?
510                                    // æŒ?®š日が日曜日の場合ã?、月曜日まで戻しますã?
511    
512                                    int shu = now.get( Calendar.DAY_OF_WEEK ) - Calendar.MONDAY ;
513    
514                                    if(      shu > 0 ) { now.add( Calendar.DATE, -shu ); }
515                                    else if( shu < 0 ) { now.add( Calendar.DATE, -6 );   }
516                            }
517                            else if( "EW".equals( prmB ) ) {                                        // 週末(日曜日)にセãƒ?ƒˆ
518                                    // 5.7.4.1 (2014/03/14) CC 引数追åŠ?
519                                    if( intC != 0 ) { now.add( Calendar.DATE,intC*7 ); }    // まずã?基準ã?日付を週単位でåŠ?¸›算するã?
520    
521                                    // 日付型æ–?­—å?入力データの終äº?—¥を日曜日にセãƒ?ƒˆしますã?
522                                    // SUNDAY=1 , MONDAY=2 になりますã?日曜日になるよã�?�«、å?に進めますã?
523                                    int shu = now.get( Calendar.DAY_OF_WEEK ) ;
524                                    if( shu != Calendar.SUNDAY ) { now.add( Calendar.DATE, 8-shu ); }
525                            }
526                            // 5.7.4.1 (2014/03/14) H1 ??HXXX ?š時を指定ã?åˆ?� けé?める処ç�?�Œ実è£?�•れてã�?�ªかったã?
527    //                      else if( prmB.startsWith( "H" ) && prmB.length() > 1 ) {
528                            else if( prmB.startsWith( "H" ) ) {
529    //                              int hour = Integer.parseInt( prmB.substring( 1 ) );
530                                    int hour = intC ;
531                                    if( prmB.length() > 1 ) { hour += Integer.parseInt( prmB.substring( 1 ) ); }
532                                    now.add( Calendar.HOUR_OF_DAY , hour );
533                            }
534    //                      else if( prmB.startsWith( "D" ) && prmB.length() > 1 ) {
535                            else if( prmB.startsWith( "D" ) ) {
536    //                              int day = Integer.parseInt( prmB.substring( 1 ) );
537                                    int day = intC ;
538                                    if( prmB.length() > 1 ) { day += Integer.parseInt( prmB.substring( 1 ) ); }
539                                    now.add( Calendar.DATE, day );
540                            }
541    //                      else if( prmB.startsWith( "M" ) && prmB.length() > 1 ) {
542                            else if( prmB.startsWith( "M" ) ) {
543    //                              int month = Integer.parseInt( prmB.substring( 1 ) );
544                                    int month = intC ;
545                                    if( prmB.length() > 1 ) { month += Integer.parseInt( prmB.substring( 1 ) ); }
546                                    now.add( Calendar.MONTH , month );
547                            }
548                            else {
549                                    // 上記ã?パターン以外ã?、数字(加減算する日数?‰なので、変換できなければ、フォーマットエラー
550                                    try {
551    //                                      int day = Integer.parseInt( prmB );
552                                            int day = Integer.parseInt( prmB ) + intC ;     // 5.7.4.1 (2014/03/14) CC 引数追åŠ?
553                                            now.add( Calendar.DATE, day );
554                                    }
555                                    catch( NumberFormatException ex ) {
556                                            String errMsg = "日付変数パラメータに、不正な値が指定されました。以下ã?中からæŒ?®šしなおしてくださいã€?
557                                                                    + "æŒ?®š可能?š[SD,ED,BSD,BED,ASD,AED,SW,EW,H1?žHXXX,D1?žDXXX,M1?žMXXX]"
558                                                                    + " prmB=[" + prmB + "]" ;
559                                            throw new RuntimeException( errMsg,ex );
560                                    }
561                            }
562                    }
563            }
564    
565            /**
566             * æŒ?®šã?引数の日付けæ–?­—å?より、カレンãƒ?‚ªブジェクトを作æ?しますã?
567             * 引数は、数字以外ã?æ–?­—を削除した状態に変換後ã?処ç�?�«回しますã?
568             * 不要なæ–?­—を削除した状態でã€?¼˜文字以上になるよã�?�«æŒ?®šしてくださいã€?
569             * 例外的にã€?¼–文字ã?場合ã?、yyyyMM01 とみなしてã€?01" æ–?­—å?を付与しますã?
570             * 引数に null を指定すると、現在時刻のカレンãƒ?‚’返しますã?
571             * それ以外ã?ãƒ??タでã€?¼˜ケタ以下ã?場合ã?、RuntimeException が発生しますã?
572             * ?˜ケタ以上14ケタ未æº??場合ã?ã€?¼˜ケタåˆ?‚’、年月日にåˆ?›¢したカレンãƒ?
573             * オブジェクトを作æ?しますã??‘4ケタ以上で初めて、時åˆ?§’を含ã‚?‚«レンãƒ?
574             * を作æ?しますã?
575             *
576             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
577             * @og.rev 5.5.8.2 (2012/11/09) value の判定に、null と ゼロæ–?­—å?を判定するã?
578             *
579             * @param value 日付けæ–?­—å?
580             *
581             * @return      カレンãƒ?‚ªブジェクãƒ?引数がnullの場合ã?、現在時刻)
582             */
583            public static final Calendar getCalendar( final String value ) {
584                    Calendar cal = Calendar.getInstance();
585    
586    //              if( value == null ) { return cal; }
587                    if( value == null || value.isEmpty() ) { return cal; }          // 5.5.8.2 (2012/11/09) null と ゼロæ–?­—å?を判定するã?
588    
589                    // 日付表記に不要なæ–?­—を削除しますã?
590                    String dateStr = parseNumber( value ) ;
591    
592                    if( dateStr.length() == 6 ) { dateStr = dateStr + "01"; }       // yyyyMM01 形式に無ç�?‚„り合わせるã?
593                    else if( dateStr.length() < 8 ) {
594                            String errMsg = "日付指定パラメータに、不正な値が指定されました。value=[" + value + "]" ;
595                            throw new RuntimeException( errMsg );
596                    }
597    
598                    cal.clear();    // 日付文字å?が存在するので、カレンãƒ?‚’リセãƒ?ƒˆ
599    
600                    int year   = Integer.parseInt( dateStr.substring( 0,4 ) );
601                    int month  = Integer.parseInt( dateStr.substring( 4,6 ) ) - 1;
602                    int date   = Integer.parseInt( dateStr.substring( 6,8 ) );
603    
604                    int hour=0, minute=0, second=0;
605                    if( dateStr.length() >= 14 ) {
606                            hour   = Integer.parseInt( dateStr.substring( 8,10 ) );
607                            minute = Integer.parseInt( dateStr.substring( 10,12 ) );
608                            second = Integer.parseInt( dateStr.substring( 12,14 ) );
609                    }
610    
611                    cal.set( year,month,date,hour,minute,second );
612    
613                    return cal;
614            }
615    
616            /**
617             * æŒ?®šã?引数の日付けæ–?­—å?(yyyyMMdd)より、日付をåŠ?®—して返しますã?
618             * マイナスを与えると、減算しますã?
619             * 日付以上ã?精度のæ–?­—å?を渡してもã?日付ã?みの計算となりますã?
620             * 結果は、引数の日付フォーマットとは全く別で、yyyyMMdd の?˜文字形式になりますã?
621             * 引数に null を渡すと、実行時の日付をベã?スとして処ç�?�—ますã?
622             *
623             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
624             *
625             * @param baseDate 日付けæ–?­—å?(yyyyMMdd)
626             * @param plus     åŠ?®—する日数(過去にするにはマイナス値を指定すã‚?
627             *
628             * @return      結果の日ä»?yyyyMMdd)
629             */
630            public static final String getDatePlus( final String baseDate,final int plus ) {
631                    Calendar cal = getCalendar( baseDate );
632                    cal.add( Calendar.DATE,plus );
633    
634                    return getDate( cal.getTimeInMillis() , "yyyyMMdd" );
635            }
636    
637            /**
638             * 現在の月に、指定ã?月数をã?ラスした日付文字å?を返しますã?
639             * 日付文字å?のフォーマットã?ã€?yyyyMM" ですã?
640             * æŒ?®šする月数にマイナスを指定すると、減算できますã?
641             *
642             * @og.rev 5.5.7.2 (2012/10/09) 新規作æ?
643             *
644             * @param baseDate 日付けæ–?­—å?(yyyyMM)
645             * @param plus     åŠ?®—する月数(過去にするにはマイナス値を指定すã‚?
646             *
647             * @return      æŒ?®šã?月数をã?ラスした日付文字å?(yyyyMM)
648             */
649            public static final String getMonthPlus( final String baseDate,final int plus ) {
650                    Calendar cal = getCalendar( baseDate );
651                    cal.set( Calendar.DATE, 1 );            // 当月の 1 日に設å®?
652                    cal.add( Calendar.MONTH , plus );
653    
654                    return getDate( cal.getTimeInMillis() , "yyyyMM" );
655            }
656    
657            /**
658             * æŒ?®šã?引数の日付けæ–?­—å?(yyyyMMdd、yyyyMMddHHmmss)に、日付をåŠ?®—して返しますã?
659             * マイナスを与えると、減算しますã?
660             *
661             * æŒ?®šする日付には、単位を付与することが可能ですã?
662             * 単位ã?、yyyyMMddHHmmss 形式ã??‘文字をæŒ?®šしますã?大æ–?­—ã?小文字も識別しますã?
663             * plus="5M" とすればã€?¼•か月ã?plus="5d"  とすればã€?¼•日 追åŠ?�—ますã?
664             * plus に単位を付けなã�??合ã?、tani にæŒ?®šã?単位を使ã�?�¾すã?
665             * plus そã?もã?がã?null かã?isEmpty の場合ã?、加算ã?ã€? になりますã?
666             *
667             * baseDate æ–?­—å?を日付文字å?に変換後ã?Calendar で計算し、結果をã?format 形式に変換しますã?
668             * 引数に null を渡すと、実行時の日付をベã?スとして処ç�?�—ますã?
669             *
670             * @og.rev 5.6.1.0 (2013/02/01) 新規作æ?
671             *
672             * @param baseDate 日付けæ–?­—å?(yyyyMMdd、yyyyMMddHHmmss 形式ã?日付文字å?)
673             * @param plus     åŠ?®—する日数(日付単位を含ã‚??単位ã?、y,M,d,H,m,s のæ–?­—で、大æ–?­—小文字ã?区別がありまã�?
674             * @param defTani  日付単位が未æŒ?®šã?場合ã?初期単ä½?'y','M','d','H','m','s' のどれか)
675             * @param format   返す日付文字å?のフォーマッãƒ?yyyyMMdd、yyyyMMddHHmmss)
676             *
677             * @return      結果の日ä»?yyyyMMdd)
678             * @throws      NumberFormatException åŠ?®—する日数の単位が('y','M','d','H','m','s')以外ã?場合ã?
679             */
680            public static final String getDatePlus( final String baseDate,final String plus,final int defTani,final String format ) {
681    
682                    int addSu = 1;                          // 初期値(plus ã�?null ã‚?Empty の場合ã?ã€?¼‹1となã‚?
683                    int tani  = defTani;
684    
685                    if( plus != null && !plus.isEmpty() ) {
686                            boolean flag = true;    // 日付単位を持ってã�?‚‹かどã�?�‹。持ってã�?‚‹場合ã?、true
687                            char ch = plus.charAt( plus.length()-1 );               // æœ?¾Œã?ä¸?–‡字を取å¾?単位か、数字本ä½?
688                            switch( ch ) {
689                                    case 'y' : tani = Calendar.YEAR;                break ;
690                                    case 'M' : tani = Calendar.MONTH;               break ;
691                                    case 'd' : tani = Calendar.DATE;                break ;
692                                    case 'H' : tani = Calendar.HOUR_OF_DAY; break ;
693                                    case 'm' : tani = Calendar.MINUTE;              break ;
694                                    case 's' : tani = Calendar.SECOND;              break ;
695                                    default  : flag = false;        break ;         // 日付単位を持ってã�?�ªã�??
696                            }
697                            if( flag ) {
698                                    addSu = Integer.parseInt( plus.substring( 0,plus.length()-1 ) );        // 日付単ä½?あり
699                            }
700                            else {
701                                    addSu = Integer.parseInt( plus ) ;                                                                      // 日付単ä½?なã�?
702                            }
703                    }
704    
705                    Calendar cal = getCalendar( baseDate );
706                    cal.add( tani,addSu );
707    
708                    return getDate( cal.getTimeInMillis() , format );
709            }
710    }