UWSCで文字列の日付変換
メールの日付をもとに、自動処理をしたくなった。
自動処理なら、UWSC。さて、問題は日付。
あれですよ、あのご立派なフォーマット。
「Thu, 17 Jun 2010 16:05:00 +0900」とか。
タイムゾーンまでついて、立派過ぎて泣けます。
こんなのパースするスクリプトを書くのは嫌です。
で考えた
UTCフォーマットねぇ。
そういえば、Javascriptで解釈できたね。
うんうん、じゃあ、ScriptControlを使って、、、。
DateTime.uws
OPTION EXPLICIT IFB GET_UWSC_NAME = "DateTime.uws" THEN PRINT DateTime.Get() + "." + DateTime.ZZ2 // Getは現在保持している日時を出力 PRINT DateTime.Get(0, "Thu, 17 Jun 2010 16:05:00 +0900") // 引数があればその値を評価 PRINT DateTime.Run("getTime") // 任意のDateオブジェクトメソッドが呼べます PRINT DateTime.Run("getUTCHours") // UTC時間も考慮されてます DateTime.Run("setUTCHours", 1, 9) // 引数のあるメソッドは、引数の数を指定してやる必要あり PRINT DateTime.Run("getHours") // メソッドの直接呼出しは、setが反映されている PRINT DateTime.HH // HHプロパティは、Getするまで反映されない DateTime.Get() // 内部保持日時と同期 PRINT DateTime.HH // HHプロパティが更新されている PRINT DateTime.GetNow() // 現在時刻を取得 PRINT DateTime.Get(1) // 1日後にして表示 DateTime.Run("setTime", 1, 0) // 基準日にする PRINT DateTime.Get() // 基準日を表示 ENDIF MODULE DateTime DIM _script PUBLIC YY, MM, DD, HH, NN, SS, ZZ, WW, YY2, MM2, DD2, HH2, NN2, SS2, ZZ2, YY4 TEXTBLOCK _src var _obj; function set(str) { _obj = new Date(str); } function setNow() { _obj = new Date(); } ENDTEXTBLOCK PROCEDURE DateTime _script = CreateOleObj("ScriptControl") _script.language = "JScript" _script.AddCode(_src) GetNow() FEND FUNCTION Get(add=0, strDate="") IF LENGTH(strDate) THEN _script.Run("set", strDate) IF add THEN Run("setTime", 1, Run("getTime") + (24*60*60*1000) * add) YY = Run("getFullYear") MM = Run("getMonth") + 1 DD = Run("getDate") HH = Run("getHours") NN = Run("getMinutes") SS = Run("getSeconds") ZZ = Run("getMilliseconds") WW = Run("getDay") YY4 = REPLACE(FORMAT(YY, 4), " ", "0") YY2 = COPY(YY4, 3) MM2 = REPLACE(FORMAT(MM, 2), " ", "0") DD2 = REPLACE(FORMAT(DD, 2), " ", "0") HH2 = REPLACE(FORMAT(HH, 2), " ", "0") NN2 = REPLACE(FORMAT(NN, 2), " ", "0") SS2 = REPLACE(FORMAT(SS, 2), " ", "0") ZZ2 = REPLACE(FORMAT(ZZ, 3), " ", "0") RESULT = YY4+"/"+MM2+"/"+DD2+" "+HH2+":"+NN2+":"+SS2 FEND FUNCTION GetNow(add=0) _script.Run("setNow") RESULT = Get(add) FEND FUNCTION RunPara(name, para[]) DIM parastr = "", evalstr = "", i IFB LENGTH(para) THEN FOR i = 0 TO LENGTH(para) - 1 IF LENGTH(parastr) THEN parastr = parastr + ", " parastr = parastr + "p" + i evalstr = evalstr + ", para[" + i + "]" NEXT ENDIF evalstr = "_script.Run(name" + evalstr + ")" COM_ERR_IGN RESULT = EVAL(evalstr) IFB COM_ERR_FLG THEN _script.AddCode("function " + name + "(" + parastr + ") { return _obj." + name + "(" + parastr + "); }") RESULT = EVAL(evalstr) ENDIF COM_ERR_RET FEND FUNCTION Run(name, num=0, p0=0, p1=0, p2=0, p3=0) HASHTBL para DIM i FOR i = 0 TO num - 1 para[i] = EVAL("p" + i) NEXT RESULT = RunPara(name, para) FEND ENDMODULE
解説自慢たらしい能書き
我ながら、なかなかシンプルトリッキーにできた。
ScriptControlのRunメソッド可変引数を、上手く吸収したつもり。
最初、getFullYearとかも、_srcテキストブロックに
function getFullYear() { return _obj.getFullYear(); }
とか書いてたんです。
_script.Run("_obj.getFullYear")
とかは動かないみたいだから。
でもそれだと、getMonthも書かなきゃいけない、、、めんどい!
面倒なのキライ!
同じようなのなら、_srcに入れてAddCodeしなくても、呼び出し時にAddCodeすれば良いじゃない。
FUNCTION Run(name) _script.AddCode("function " + name + "() { return _obj." + name + "(); }") RESULT = _script.Run(name) FEND
二回以上同じメソッドを呼ぶなら、AddCodeいらんね。
FUNCTION Run(name) COM_ERR_IGN RESULT = _script.Run(name) IFB COM_ERR_FLG THEN _script.AddCode("function " + name + "() { return _obj." + name + "(); }") RESULT = _script.Run(name) ENDIF COM_ERR_RET FEND
あー、setHoursとかもしたくなるかなぁ、、、。
引数ねぇ、、、可変ねぇ、、、。
可変といえば、連想配列。うん、配列。
それにEVALか。
あと、いちいち配列を作るのは面倒、と思って出来上がりました。
Get関数のリターンは、こちらの都合。
と言いますか、日本人に優しくてGETTIMEが飲むフォーマット。
でも、これがあればGETTIMEは不要だったりもします。
Getメソッドは、GETTIMEと同じ引数です。
また、自力で翌日にしたい場合は、こんな感じ。
DateTime.Run("setTime", 1, DateTime.Run("getTime") + (24 * 60 * 60 * 1000)) // 1日後にする PRINT DateTime.Get() // 1日後を表示
ミリ秒単位で、加減算が可能です。
なお、基準日は1970年1月1日0時ちょうど(UTC)。
日本時間ですと、1月1日の9時ちょうどとなります。
GETTIMEの戻り値とは、30年と-9時間と1000倍の差があります。
そんなわけで、UWSCでUTCフォーマットの日付を変換するスクリプトのように書いてますが、実態はJavascriptによる変換に依存しまくりで、スクリプトとしての売りは、可変引数のメソッドの呼び出し、かも。
どう応用するかは、不明ですけど、、、。