OSDN Git Service

Ver8.5.2.0
[opengion/opengionV8.git] / uap / webapps / gf / src / org / opengion / fukurou / system / DateSet.java
1 /*
2  * Copyright (c) 2009 The openGion Project.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific language
14  * governing permissions and limitations under the License.
15  */
16 package org.opengion.fukurou.system;                                                            // 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system
17
18 import java.io.FileInputStream;
19 import java.io.FileOutputStream;
20 import java.util.Date;
21 import java.util.Locale;
22 // import java.util.Calendar;                                                                                   // 7.0.1.4 (2018/11/26)
23 import java.util.concurrent.ConcurrentMap;                                                      // 7.0.1.3 (2018/11/12)
24 import java.util.concurrent.ConcurrentHashMap;                                          // 7.0.1.3 (2018/11/12)
25 import java.text.DateFormat;
26 import java.text.SimpleDateFormat;
27
28 // import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;   // 6.1.0.0 (2014/12/26) refactoring
29
30 /**
31  * DateSet.java は、入力ファイルの日付、時刻キーワードを実行時の日時で変換して出力します。
32  *
33  * 変換には、$(yyyy)の形式で指定し、カッコの文字列は java.text.SimpleDateFormat で使用する
34  * 時刻フォーマット構文を用います。
35  * また、引数に keys,vals を渡すことで、$(KEY1) 文字列を VAL1 文字列と置き換えます。
36  *
37  *  サンプルファイル
38  *  $(yyyy/MM/dd)        年/月/日を表します。
39  *  $(yy)                年だけを2桁で表します。
40  *  $(MM)                月を2桁 (02,03など)で表します。
41  *  $(dd)                日を2桁 (02,03など)で表します。
42  *  $(HH:mm:ss)          時:分:秒を表します。
43  *  $(MMMMMMMM)          月をフルスペルで表します。
44  *  $(MMM)               月を3桁固定(Mar,Aplなど)で表します。
45  *  $(EEEEEEEE)          曜日をフルスペルで表します。
46  *  $(EEE)               曜日を3桁固定(Sun,Monなど)で表します。
47  *
48  *  // 7.0.1.3 (2018/11/12)                                                      2019/01/01    2030/01/01
49  *  $(ATIME)             通算秒数( new Date().getTime()/1000 )  の 10桁文字列    1546268400    1893423600
50  *  $(BTIME)             通算分数( new Date().getTime()/60000 ) の  8桁文字列      25771140      31557060
51  *    ※ BTIME が桁あふれするのは、2160/02/18 です。
52  *
53  *   時刻フォーマット構文
54  *
55  *   記号     意味                    表示                例
56  *   ------   -------                 ------------        -------
57  *   G        年号                    (テキスト)          AD
58  *   y        年                      (数値)              1996
59  *   M        月                      (テキスト & 数値)  July & 07
60  *   d        日                      (数値)              10
61  *   h        午前/午後の時 (1~12)    (数値)              12
62  *   H        一日における時 (0~23)   (数値)              0
63  *   m        分                      (数値)              30
64  *   s        秒                      (数値)              55
65  *   S        ミリ秒                  (数値)              978
66  *   E        曜日                    (テキスト)          火曜日
67  *   D        年における日            (数値)              189
68  *   F        月における曜日          (数値)              2 (7月の第2水曜日)
69  *   w        年における週            (数値)              27
70  *   W        月における週            (数値)              2
71  *   a        午前/午後               (テキスト)          PM
72  *   k        一日における時 (1~24)   (数値)              24
73  *   K        午前/午後の時 (0~11)    (数値)              0
74  *   z        時間帯                  (テキスト)          PDT
75  *   '        テキスト用エスケープ
76  *   ''       単一引用符                                  '
77  *
78  *  パターン文字のカウントによって、そのフォーマットが決まります。
79  *  (テキスト): 4以上: フル形式を使用します。4以下: 短いまたは省力された形式があれば、それを使用します。
80  *
81  *  (数値): 最小桁数。これより短い数値は、この桁数までゼロが追加されます。年には特別な処理があります。
82  *  つまり、'y'のカウントが2なら、年は2桁に短縮されます。
83  *
84  *  (テキスト & 数値): 3以上ならテキストを、それ以外なら数値を使用します。
85  *
86  *  パターンの文字が['a'..'z']と['A'..'Z']の範囲になければ、その文字は引用テキストとして扱われます。
87  *  たとえば、':'、'.'、' '、'#'、'@'などの文字は、単一引用符に囲まれていなくても、
88  *  結果の時刻テキストに使用されます。
89  *
90  *  無効なパターン文字がパターンに入っていると、フォーマットや解析で例外がスローされます。
91  *
92  *  USロケールを使った例:
93  *
94  *   フォーマットパターン                   結果
95  *   --------------------                   ----
96  *   "yyyy.MM.dd G 'at' hh:mm:ss z"    ⇒  1996.07.10 AD at 15:08:56 PDT
97  *   "EEE, MMM d, ''yy"                ⇒  Wed, July 10, '96
98  *   "h:mm a"                          ⇒  12:08 PM
99  *   "hh 'o''''clock' a, zzzz"         ⇒  12 o'clock PM, Pacific Daylight Time
100  *   "K:mm a, z"                       ⇒  0:00 PM, PST
101  *   "yyyyy.MMMMM.dd GGG hh:mm aaa"    ⇒  1996.July.10 AD 12:08 PM
102  *
103  * @og.rev 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system
104  * @og.rev 7.0.1.3 (2018/11/12) keys,valsをMapに変更。BUILD_TYPEのビルド番号を100秒単位に変更。
105  *
106  * @version  0.9.0  1999/03/09
107  * @author   Kazuhiko Hasegawa
108  * @since    JDK1.1,
109  */
110 public class DateSet {
111         private final ConcurrentMap<String,String> prmMap = new ConcurrentHashMap<>();          // 7.0.1.3 (2018/11/12)
112
113 //      private String[] keys ;
114 //      private String[] vals ;
115
116         /**
117          * デフォルトコンストラクター
118          *
119          * Mapの初期値を設定しておきます。
120          *
121          * @og.rev 7.0.1.3 (2018/11/12) KeysValsは、Mapに置き換え
122          * @og.rev 7.0.1.4 (2018/11/26) ATIME,BTIME 追加
123          */
124         public DateSet() {
125                 prmMap.put( "ATIME" ,  Long.toString( new Date().getTime()/1000 ) );            // 
126                 prmMap.put( "BTIME" ,  Long.toString( new Date().getTime()/60000 ) );           // 
127
128         //      final Calendar now = Calendar.getInstance();
129         //      final int tm = ( now.get( Calendar.HOUR_OF_DAY ) * 60 + now.get( Calendar.MINUTE ) ) / 15 ;             // 0 ~ 96未満の数値になる
130
131         //      final String CTIME = getDate( "yyDDD" ) + String.format( "%02d" , tm ) ;
132         //      prmMap.put( "CTIME" ,  CTIME );
133         }
134
135         /**
136          * フォーマット解析時に置き換える キーと値のMapを設定します。
137          *
138          * $(KEY1) 文字列を VAL1 文字列と置き換える処理を行います。これにより日付以外の
139          * 文字列を置き換える処理を実行できます。
140          *
141          * @og.rev 7.0.1.3 (2018/11/12) KeysValsは、Mapに置き換え
142          *
143          * @param       pMap    置き換え元のMap
144          */
145         public void setParamMap( final ConcurrentMap<String,String> pMap ) {
146                 if( pMap != null ) {
147                          prmMap.putAll( pMap );
148                 }
149         }
150
151 //      /**
152 //       * フォーマット解析時に置き換える キーと値の配列を設定します。
153 //       *
154 //       * $(KEY1) 文字列を VAL1 文字列と置き換える処理を行います。これにより日付以外の
155 //       * 文字列を置き換える処理を実行できます。
156 //       *
157 //       * @og.rev 7.0.1.3 (2018/11/12) KeysValsは、Mapに置き換え
158 //       *
159 //       * @param       inkeys  置き換え元キー配列
160 //       * @param       invals  置き換え元値配列
161 //       */
162 //      public void setKeysVals( final String[] inkeys, final String[] invals ) {
163 //              if( inkeys != null && invals != null && inkeys.length == invals.length ) {
164 //                      final int size = inkeys.length ;
165 //                      keys = new String[size];
166 //                      vals = new String[size];
167 //                      System.arraycopy( inkeys,0,keys,0,size );
168 //                      System.arraycopy( invals,0,vals,0,size );
169 //              }
170 //      }
171
172         /**
173          * 現在日付、時刻をフォーマット指定個所に埋め込みます。
174          * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。
175          *
176          * @og.rev 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。
177          * @og.rev 6.4.2.0 (2016/01/29) fukurou.util.StringUtil → fukurou.system.HybsConst に変更
178          *
179          * @param       inByte  変換元バイト配列(可変長引数)
180          * @return      変換後のバイト配列
181          */
182         public byte[] change( final byte... inByte ) {
183                 byte[] outByte = new byte[inByte.length+100];
184                 int add = 0;
185                 for( int i=0; i<inByte.length; i++ ) {
186                         if( inByte[i] == '$' && i<inByte.length-1 && inByte[i+1] == '(' ) {
187                                 int j = 0;
188                                 while( inByte[i+j+2] != ')') { j++; }
189                                 final String str = changeForm( new String( inByte,i+2,j,HybsConst.DEFAULT_CHARSET ) );          // 6.4.2.0 (2016/01/29)
190                                 final byte[] byteDate = str.getBytes( HybsConst.DEFAULT_CHARSET ) ;                                                     // 6.4.2.0 (2016/01/29)
191                                 // 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。
192                                 System.arraycopy( byteDate,0,outByte,add,byteDate.length );             // 6.3.6.0 (2015/08/16)
193                                 add += byteDate.length ;                                                                                // 6.3.6.0 (2015/08/16)
194                                 i   += j+2;
195                         }
196                         else {
197                                 outByte[add] = inByte[i];
198                                 add++;
199                         }
200                 }
201                 final byte[] rtnByte = new byte[add];
202                 System.arraycopy( outByte,0,rtnByte,0,add );
203                 return rtnByte;
204         }
205
206         /**
207          * パラメータの変換、および、現在日付、時刻のフォーマット変換を行います。
208          *
209          * 先に、パラメータの変換を行います。form が、Mapのkey にマッチすれば、
210          * その値を返します。マッチしなければ、時刻のフォーマット変換を行います。
211          * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。
212          *
213          * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
214          * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
215          * @og.rev 7.0.1.3 (2018/11/12) KeysValsは、Mapに置き換え
216          *
217          * @param       form フォーム文字列 ( 例 "yyyy/MM/dd HH:mm:ss" )
218          *
219          * @return      フォーマット変換結果
220          */
221         public String changeForm( final String form ) {
222                 // Map#getOrDefault( key,defVal )はdefValも評価が必ず実行されるため、使えない。
223                 // return prmMap.getOrDefault( form,DateSet.getDate( form ) ;
224
225                 final String rtn = prmMap.get( form );
226
227                 return rtn == null ? DateSet.getDate( form ) : rtn ;
228
229 //              // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
230 //              if( keys != null && vals != null ) {
231 //                      for( int i=0; i<keys.length; i++ ) {
232 //                              if( form.equals( keys[i] ) ) {
233 //                                      return vals[i];
234 //                              }
235 //                      }
236 //              }
237 //
238 //              return DateSet.getDate( form );
239         }
240
241         /**
242          * パラメータの変換、および、現在日付、時刻のフォーマット変換を行います。
243          *
244          * 先に、パラメータの変換を行います。form が、Mapのkey にマッチすれば、
245          * その値を返します。マッチしなければ、時刻のフォーマット変換を行います。
246          * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。
247          *
248          * @param       form フォーム文字列 ( 例 "yyyy/MM/dd HH:mm:ss" )
249          *
250          * @return      フォーマット変換結果
251          * @og.rtnNotNull
252          */
253         public String changeString( final String form ) {
254                 final StringBuilder buf = new StringBuilder( HybsConst.BUFFER_MIDDLE );
255                 int bkst = 0;
256                 int st = form.indexOf( "$(" );
257                 while( st >= 0 ) {
258                         buf.append( form.substring( bkst,st ) );
259                         final int ed = form.indexOf( ')',st+2 );                                // 6.0.2.5 (2014/10/31) refactoring
260                         buf.append( changeForm( form.substring( st+2,ed ) ) );
261                         bkst = ed + 1;
262                         st = form.indexOf( "$(",bkst );
263                 }
264                 buf.append( form.substring( bkst ) );
265
266                 return buf.toString();
267         }
268
269         /**
270          * 現在日付、時刻を指定のフォーマットで文字列に変換して返します。
271          * 出力フォーマットは、"yyyy/MM/dd HH:mm:ss" 固定です。
272          *
273          * @og.rev 5.5.7.2 (2012/10/09) 新規作成
274          * @og.rev 6.4.2.0 (2016/01/29) fukurou.util.HybsDateUtil → fukurou.system.DateSet に変更
275          *
276          * @return      現在日付、時刻 ( 例 2012/09/05 18:10:24 )
277          * @og.rtnNotNull
278          */
279         public static String getDate() {
280                 final DateFormat formatter = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss",Locale.JAPAN );
281                 return formatter.format( new Date() );
282         }
283
284         /**
285          * 現在時刻を指定のフォーマットで文字列に変換して返します。
286          * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。
287          * 変換時のロケーションは、Locale.JAPAN です。
288          * 現在時刻は、new Date() で求めます。
289          *
290          * @param       form フォーム文字列 ( 例 "yyyy/MM/dd HH:mm:ss.SSS" )
291          *
292          * @og.rev 5.5.7.2 (2012/10/09) 新規作成
293          * @og.rev 6.4.2.0 (2016/01/29) fukurou.util.HybsDateUtil → fukurou.system.DateSet に変更
294          *
295          * @return      現在日付、時刻
296          * @og.rtnNotNull
297          * @see         java.text.SimpleDateFormat
298          */
299         public static String getDate( final String form ) {
300                 final DateFormat formatter = new SimpleDateFormat( form,Locale.JAPAN );
301                 return formatter.format( new Date() );
302         }
303
304         /**
305          * 指定時刻を指定のフォーマットで文字列に変換して返します。
306          * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。
307          * 変換時のロケーションは、Locale.JAPAN です。
308          * 指定時刻は、new Date( time ) で求めます。
309          *
310          * @param       time 指定のカレントタイムのロング値
311          * @param       form フォーム文字列 ( 例 "yyyy/MM/dd HH:mm:ss.SSS" )
312          *
313          * @og.rev 5.5.7.2 (2012/10/09) 新規作成
314          * @og.rev 6.4.2.0 (2016/01/29) fukurou.util.HybsDateUtil → fukurou.system.DateSet に変更
315          *
316          * @return      現在日付、時刻( 例 2001/04/17 15:48:22 )
317          * @og.rtnNotNull
318          */
319         public static String getDate( final long time,final String form ) {
320                 final DateFormat formatter = new SimpleDateFormat( form,Locale.JAPAN );
321                 return formatter.format( new Date( time ) );
322         }
323
324         /**
325          * 入力ファイルの時刻フォーマットを変換して出力ファイルに書き込みます。
326          *
327          * 引数に &lt;key1&gt; &lt;val1&gt; のペア情報を渡すことが可能です。
328          * 先に、keys,vals の変換を行います。form が、keys にマッチすれば、vals を
329          * 返します。最後までマッチしなければ、時刻のフォーマット変換を行います。
330          * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。
331          * フォーム文字列例 (  "yyyy/MM/dd HH:mm:ss" )
332          *
333          * @og.rev 7.0.1.3 (2018/11/12) KeysValsは、Mapに置き換え
334          *
335          * @param       args 引数配列( 入力ファイル 出力ファイル キー1 値1 ・・・
336          * @throws Throwable なんらかのエラーが発生した場合。
337          */
338         public static void main( final String[] args ) throws Throwable {
339                 if( args.length > 2 && ( args.length % 2 != 0 ) ) {
340                         System.err.println( "Usage: java org.opengion.fukurou.system.DateSet <inputFile> <outputFile> [<key1> <val1> ・・・]" );
341                         return ;
342                 }
343
344                 final ConcurrentMap<String,String> prmMap = new ConcurrentHashMap<>();          // 7.0.1.3 (2018/11/12)
345
346                 for( int i=2; i<args.length; i+=2 ) {
347                         prmMap.put( args[i] , args[i+1] );
348                 }
349
350 //              String[] keys = new String[ (args.length-2)/2 ];
351 //              String[] vals = new String[ (args.length-2)/2 ];
352 //              for( int i=1; i<=keys.length; i++ ) {
353 //                      keys[i-1] = args[i*2];
354 //                      vals[i-1] = args[i*2+1];
355 //              }
356
357                 final FileInputStream filein = new FileInputStream( args[0] );
358                 final byte[] byteIn = new byte[ filein.available() ];
359                 final int len = filein.read( byteIn );
360                 if( len != byteIn.length ) {
361                         final String errMsg = "読み取りファイルのデータが切り捨てられました。" +
362                                                         "File=" + args[0] + " Length=" + len  + " Input=" + byteIn.length ;
363                         System.err.println( errMsg );
364                 }
365                 filein.close();
366
367                 final DateSet dateSet = new DateSet();
368 //              dateSet.setKeysVals( keys,vals );
369                 dateSet.setParamMap( prmMap );
370                 final byte[] byteout = dateSet.change( byteIn );
371
372                 final FileOutputStream fileout = new FileOutputStream( args[1] );
373                 fileout.write( byteout );
374                 fileout.close();
375         }
376 }