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倍の差があります。


そんなわけで、UWSCUTCフォーマットの日付を変換するスクリプトのように書いてますが、実態はJavascriptによる変換に依存しまくりで、スクリプトとしての売りは、可変引数のメソッドの呼び出し、かも。
どう応用するかは、不明ですけど、、、。