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.fukurou.system; // 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system 017 018import java.io.FileInputStream; 019import java.io.FileOutputStream; 020import java.util.Date; 021import java.util.Locale; 022import java.text.DateFormat; 023import java.text.SimpleDateFormat; 024 025import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 026 027/** 028 * DateSet.java は、入力ファイルの日付,時刻キーワードを実行時の日時で変換して,出力します。 029 * 030 * 変換には,$(yyyy)の形式で指定し,カッコの文字列は,java.text.SimpleDateFormat で使用する, 031 * 時刻フォーマット構文を用います。 032 * また、引数に keys,vals を渡すことで、$(KEY1) 文字列を VAL1 文字列と置き換えます。 033 * 034 * サンプルファイル 035 * $(yyyy/MM/dd) 年/月/日を表します。 036 * $(yy) 年だけを2桁で表します。 037 * $(MM) 月を2桁 (02,03など)で表します。 038 * $(dd) 日を2桁 (02,03など)で表します。 039 * $(HH:mm:ss) 時:分:秒を表します。 040 * $(MMMMMMMM) 月をフルスペルで表します。 041 * $(MMM) 月を3桁固定(Mar,Aplなど)で表します。 042 * $(EEEEEEEE) 曜日をフルスペルで表します。 043 * $(EEE) 曜日を3桁固定(Sun,Monなど)で表します。 044 * 045 * 時刻フォーマット構文 046 * 047 * 記号 意味 表示 例 048 * ------ ------- ------------ ------- 049 * G 年号 (テキスト) AD 050 * y 年 (数値) 1996 051 * M 月 (テキスト & 数値) July & 07 052 * d 日 (数値) 10 053 * h 午前/午後の時 (1~12) (数値) 12 054 * H 一日における時 (0~23) (数値) 0 055 * m 分 (数値) 30 056 * s 秒 (数値) 55 057 * S ミリ秒 (数値) 978 058 * E 曜日 (テキスト) 火曜日 059 * D 年における日 (数値) 189 060 * F 月における曜日 (数値) 2 (7月の第2水曜日) 061 * w 年における週 (数値) 27 062 * W 月における週 (数値) 2 063 * a 午前/午後 (テキスト) PM 064 * k 一日における時 (1~24) (数値) 24 065 * K 午前/午後の時 (0~11) (数値) 0 066 * z 時間帯 (テキスト) PDT 067 * ' テキスト用エスケープ 068 * '' 単一引用符 ' 069 * 070 * パターン文字のカウントによって、そのフォーマットが決まります。 071 * (テキスト): 4以上: フル形式を使用します。4以下: 短いまたは省力された形式があれば、それを使用します。 072 * 073 * (数値): 最小桁数。これより短い数値は、この桁数までゼロが追加されます。年には特別な処理があります。 074 * つまり、'y'のカウントが2なら、年は2桁に短縮されます。 075 * 076 * (テキスト & 数値): 3以上ならテキストを、それ以外なら数値を使用します。 077 * 078 * パターンの文字が['a'..'z']と['A'..'Z']の範囲になければ、その文字は引用テキストとして扱われます。 079 * たとえば、':'、'.'、' '、'#'、'@'などの文字は、単一引用符に囲まれていなくても、 080 * 結果の時刻テキストに使用されます。 081 * 082 * 無効なパターン文字がパターンに入っていると、フォーマットや解析で例外がスローされます。 083 * 084 * USロケールを使った例: 085 * 086 * フォーマットパターン 結果 087 * -------------------- ---- 088 * "yyyy.MM.dd G 'at' hh:mm:ss z" ⇒ 1996.07.10 AD at 15:08:56 PDT 089 * "EEE, MMM d, ''yy" ⇒ Wed, July 10, '96 090 * "h:mm a" ⇒ 12:08 PM 091 * "hh 'o''''clock' a, zzzz" ⇒ 12 o'clock PM, Pacific Daylight Time 092 * "K:mm a, z" ⇒ 0:00 PM, PST 093 * "yyyyy.MMMMM.dd GGG hh:mm aaa" ⇒ 1996.July.10 AD 12:08 PM 094 * 095 * @og.rev 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system 096 * 097 * @version 0.9.0 1999/03/09 098 * @author Kazuhiko Hasegawa 099 * @since JDK1.1, 100 */ 101public class DateSet { 102 private String[] keys ; 103 private String[] vals ; 104 105 /** 106 * フォーマット解析時に置き換える キーと値の配列を設定します。 107 * 108 * $(KEY1) 文字列を VAL1 文字列と置き換える処理を行います。これにより日付以外の 109 * 文字列を置き換える処理を実行できます。 110 * 111 * @param inkeys 置き換え元キー配列 112 * @param invals 置き換え元値配列 113 */ 114 public void setKeysVals( final String[] inkeys, final String[] invals ) { 115 if( inkeys != null && invals != null && inkeys.length == invals.length ) { 116 final int size = inkeys.length ; 117 keys = new String[size]; 118 vals = new String[size]; 119 System.arraycopy( inkeys,0,keys,0,size ); 120 System.arraycopy( invals,0,vals,0,size ); 121 } 122 } 123 124 /** 125 * 現在日付、時刻をフォーマット指定個所に埋め込みます。 126 * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。 127 * 128 * @og.rev 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。 129 * @og.rev 6.4.2.0 (2016/01/29) fukurou.util.StringUtil → fukurou.system.HybsConst に変更 130 * 131 * @param inByte 変換元バイト配列(可変長引数) 132 * @return 変換後のバイト配列 133 */ 134 public byte[] change( final byte... inByte ) { 135 byte[] outByte = new byte[inByte.length+100]; 136 int add = 0; 137 for( int i=0; i<inByte.length; i++ ) { 138 if( inByte[i] == '$' && i<inByte.length-1 && inByte[i+1] == '(' ) { 139 int j = 0; 140 while( inByte[i+j+2] != ')') { j++; } 141 final String str = changeForm( new String( inByte,i+2,j,HybsConst.DEFAULT_CHARSET ) ); // 6.4.2.0 (2016/01/29) 142 final byte[] byteDate = str.getBytes( HybsConst.DEFAULT_CHARSET ) ; // 6.4.2.0 (2016/01/29) 143 // 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。 144 System.arraycopy( byteDate,0,outByte,add,byteDate.length ); // 6.3.6.0 (2015/08/16) 145 add += byteDate.length ; // 6.3.6.0 (2015/08/16) 146 i += j+2; 147 } 148 else { 149 outByte[add] = inByte[i]; 150 add++; 151 } 152 } 153 final byte[] rtnByte = new byte[add]; 154 System.arraycopy( outByte,0,rtnByte,0,add ); 155 return rtnByte; 156 } 157 158 /** 159 * keys,vals の変換、および、現在日付、時刻のフォーマット変換を行います。 160 * 161 * 先に、keys,vals の変換を行います。form が、keys にマッチすれば、vals を 162 * 返します。最後までマッチしなければ、時刻のフォーマット変換を行います。 163 * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。 164 * 165 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。 166 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 167 * 168 * @param form フォーム文字列 ( 例 "yyyy/MM/dd HH:mm:ss" ) 169 * 170 * @return フォーマット変換結果 171 */ 172 public String changeForm( final String form ) { 173 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 174 if( keys != null && vals != null ) { 175 for( int i=0; i<keys.length; i++ ) { 176 if( form.equals( keys[i] ) ) { 177 return vals[i]; 178 } 179 } 180 } 181 182 return DateSet.getDate( form ); 183 } 184 185 /** 186 * keys,vals の変換、および、現在日付、時刻のフォーマット変換を行います。 187 * 188 * 先に、keys,vals の変換を行います。form が、keys にマッチすれば、vals を 189 * 返します。最後までマッチしなければ、時刻のフォーマット変換を行います。 190 * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。 191 * 192 * @param form フォーム文字列 ( 例 "yyyy/MM/dd HH:mm:ss" ) 193 * 194 * @return フォーマット変換結果 195 * @og.rtnNotNull 196 */ 197 public String changeString( final String form ) { 198 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); 199 int bkst = 0; 200 int st = form.indexOf( "$(" ); 201 while( st >= 0 ) { 202 buf.append( form.substring( bkst,st ) ); 203 final int ed = form.indexOf( ')',st+2 ); // 6.0.2.5 (2014/10/31) refactoring 204 buf.append( changeForm( form.substring( st+2,ed ) ) ); 205 bkst = ed + 1; 206 st = form.indexOf( "$(",bkst ); 207 } 208 buf.append( form.substring( bkst ) ); 209 210 return buf.toString(); 211 } 212 213 /** 214 * 現在日付、時刻を指定のフォーマットで文字列に変換して返します。 215 * 出力フォーマットは、"yyyy/MM/dd HH:mm:ss" 固定です。 216 * 217 * @og.rev 5.5.7.2 (2012/10/09) 新規作成 218 * @og.rev 6.4.2.0 (2016/01/29) fukurou.util.HybsDateUtil → fukurou.system.DateSet に変更 219 * 220 * @return 現在日付、時刻 ( 例 2012/09/05 18:10:24 ) 221 * @og.rtnNotNull 222 */ 223 public static String getDate() { 224 final DateFormat formatter = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss",Locale.JAPAN ); 225 return formatter.format( new Date() ); 226 } 227 228 /** 229 * 現在時刻を指定のフォーマットで文字列に変換して返します。 230 * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。 231 * 変換時のロケーションは、Locale.JAPAN です。 232 * 現在時刻は、new Date() で求めます。 233 * 234 * @param form フォーム文字列 ( 例 "yyyy/MM/dd HH:mm:ss.SSS" ) 235 * 236 * @og.rev 5.5.7.2 (2012/10/09) 新規作成 237 * @og.rev 6.4.2.0 (2016/01/29) fukurou.util.HybsDateUtil → fukurou.system.DateSet に変更 238 * 239 * @return 現在日付、時刻 240 * @og.rtnNotNull 241 * @see java.text.SimpleDateFormat 242 */ 243 public static String getDate( final String form ) { 244 final DateFormat formatter = new SimpleDateFormat( form,Locale.JAPAN ); 245 return formatter.format( new Date() ); 246 } 247 248 /** 249 * 指定時刻を指定のフォーマットで文字列に変換して返します。 250 * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。 251 * 変換時のロケーションは、Locale.JAPAN です。 252 * 指定時刻は、new Date( time ) で求めます。 253 * 254 * @param time 指定のカレントタイムのロング値 255 * @param form フォーム文字列 ( 例 "yyyy/MM/dd HH:mm:ss.SSS" ) 256 * 257 * @og.rev 5.5.7.2 (2012/10/09) 新規作成 258 * @og.rev 6.4.2.0 (2016/01/29) fukurou.util.HybsDateUtil → fukurou.system.DateSet に変更 259 * 260 * @return 現在日付、時刻( 例 2001/04/17 15:48:22 ) 261 * @og.rtnNotNull 262 */ 263 public static String getDate( final long time,final String form ) { 264 final DateFormat formatter = new SimpleDateFormat( form,Locale.JAPAN ); 265 return formatter.format( new Date( time ) ); 266 } 267 268 /** 269 * 入力ファイルの時刻フォーマットを変換して出力ファイルに書き込みます。 270 * 271 * 引数に <key1> <val1> のペア情報を渡すことが可能です。 272 * 先に、keys,vals の変換を行います。form が、keys にマッチすれば、vals を 273 * 返します。最後までマッチしなければ、時刻のフォーマット変換を行います。 274 * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。 275 * フォーム文字列例 ( "yyyy/MM/dd HH:mm:ss" ) 276 * 277 * @param args 引数配列( 入力ファイル 出力ファイル キー1 値1 ・・・ 278 * @throws Throwable なんらかのエラーが発生した場合。 279 */ 280 public static void main( final String[] args ) throws Throwable { 281 if( args.length > 2 && ( args.length % 2 != 0 ) ) { 282 System.err.println( "Usage: java org.opengion.fukurou.system.DateSet <inputFile> <outputFile> [<key1> <val1> ・・・]" ); 283 return ; 284 } 285 286 String[] keys = new String[ (args.length-2)/2 ]; 287 String[] vals = new String[ (args.length-2)/2 ]; 288 for( int i=1; i<=keys.length; i++ ) { 289 keys[i-1] = args[i*2]; 290 vals[i-1] = args[i*2+1]; 291 } 292 293 final FileInputStream filein = new FileInputStream( args[0] ); 294 final byte[] byteIn = new byte[ filein.available() ]; 295 final int len = filein.read( byteIn ); 296 if( len != byteIn.length ) { 297 final String errMsg = "読み取りファイルのデータが切り捨てられました。" + 298 "File=" + args[0] + " Length=" + len + " Input=" + byteIn.length ; 299 System.err.println( errMsg ); 300 } 301 filein.close(); 302 303 final DateSet dateSet = new DateSet(); 304 dateSet.setKeysVals( keys,vals ); 305 final byte[] byteout = dateSet.change( byteIn ); 306 307 final FileOutputStream fileout = new FileOutputStream( args[1] ); 308 fileout.write( byteout ); 309 fileout.close(); 310 } 311}