ShiftDate関数(TKInfo.dll)についてNo.07671
山紫水明 さん 13/01/20 14:36
 

秀まるおさん,
 次のマクロは秀丸メールでは正しく動いていますが,秀丸エディタ上では動きが
おかしいようです。こういうものでしょうか。

//---------------------------------------------------------------
openreg "CURRENTUSER","Software\\Hidemaruo\\TuruKame\\Config";
if( result ) {
    loaddll getregstr("TuruKameDir") + "tkinfo.dll";
    $date = "Sun, 13 Jan 2013 11:02:28 +0900 (JST)";
    message $date;
    message dllfuncstr("FormatDate", $date, "YYYY/MM/DD(W) hh:mm:ss");
    $date1 = dllfuncstr("ShiftDate", $date, "-7");    // 一週間前。
    $date1 = dllfuncstr("FormatDate", $date1, "YYYY/MM/DD(W) hh:mm:ss");
    message $date1;
    $date2 = dllfuncstr("ShiftDate", $date, "月");    // その週の月曜日。
    $date2 = dllfuncstr("FormatDate", $date2, "YYYY/MM/DD(W) hh:mm:ss");
    message $date2;
    $date3 = dllfuncstr("ShiftDate", $date, "+5.30");    // 5時間30分後
    $date3 = dllfuncstr("FormatDate", $date3, "YYYY/MM/DD(W) hh:mm:ss");
    message $date3;
    freedll;
}
closereg;
endmacro;
//---------------------------------------------------------------

 Windows Vista + 秀丸エディタ Ver.8.30 β18 浮動小数点数版 です。
 
              山紫水明

[ ]
RE:07671 ShiftDate関数(TKInfo.dll)にNo.07673
秀まるお さん 13/01/21 12:10
 
 テストしてみたらたしかにダメでした。tkinfo.dllがDate:ヘッダ互換の日付
文字列を生成するのにTuruKame.exe側の処理を呼び出して処理させようとしてて、
それが失敗してました。

 tkinfo.dllの中だけで処理出来るように修正させていただきます。

[ ]
RE:07673 ShiftDate関数(TKInfo.dll)にNo.07674
秀まるお さん 13/01/21 14:18
 
 ついでに、FormatDateもダメでした。CurrentDate関数も、パラメータ無しだ
とダメでした。その辺も直します。

[ ]
RE:07674 ShiftDate関数(TKInfo.dll)にNo.07680
山紫水明 さん 13/01/24 22:50
 
 秀まるおさん,

β27で修正を確認しました。ご苦労さまでした。

ShiftDate関数について,以下気づいた点です。
1.マイナスの日数指定は,今日の時点では41296までのようで,これ以上数字を大
    きくすると年が不正確になります。1900年以降に適用できるのが仕様ということ
    でよろしいでしょうか。
2.プラスの記号は省略してもいいようですが,それでいいでしょうか。
3.秒の指定は無効のようですが,これは仕様でしょうか。
5.例題の説明に
 $date = dllfuncstr("ShiftDate", $date, "月");    // 先週の月曜日
とありますが,これは「その週の月曜日」あるいは「パラメータ1の属する週の月曜
日」ではないでしょうか。

 それと別件で,前にも話題になったような気がしますが,秀丸エディタで使用する
場合,秀丸メールがインストールしてある環境では問題ないのですが,勤務先によっ
てはインストールできない事情もあると思います。
 マクロを公開する場合に,「秀丸エディタの正規のユーザーで秀丸メールをインス
トールしていない人は,tkinfo.dll だけをマクロ用のフォルダにコピーできま
す。」
という主旨をドキュメントに書いても差し支えありませんか。

                          山紫水明

[ ]
RE:07680 ShiftDate関数(TKInfo.dll)にNo.07682
秀まるお さん 13/01/25 11:06
 
 β27ですが、すみませんが1つバグがあって、タイムゾーンの分(日本だと9
時間)のずれが出てしまってると思います。β28だと大丈夫なので、すみません
がβ28に入れ替えお願いします。

 以下、β28を元にしてお返事させていただきます。

> 1.マイナスの日数指定は,今日の時点では41296までのようで,これ以上数字を大
>     きくすると年が不正確になります。1900年以降に適用できるのが仕様ということ
>     でよろしいでしょうか。

 β28でテストした限りはですが、こちらでは1900年よりも前でもうまく計算す
るようでした。Windows7とWindowsXPの仮想環境でテストして大丈夫そうでした。

 実は、日時の計算は、WindowsのFILETIME構造体 = 64bit整数で計算してまし
て、その値は、

   1601 年 1 月 1 日 1 時以降の 100 ナノ秒の間隔の数を表す 64 ビット値

 と定義されてます。なので、1601年以降ならうまく計算してくれる物かと思い
ます。

 Windowsの種類によっては1900年以降しか正しく動作しないってことなのかも
しれませんけども、ちょっとよく分からないです。

 テストしたマクロの例:

    loaddll "tkinfo.dll";
    $date = dllfuncstr( "CurrentDate" );
    message $date;
    $date = dllfuncstr("ShiftDate", $date, "-99999");
    message $date;

 ちなみにtkinfo.dllの中での計算は、SystemTimeToFileTime/
FileTimeToSystemTime関数を呼び出して、日付を64bit整数に変換したり戻した
りってことでやってます。それらAPIの説明を見た限りでは、特に1900年以降で
ないとダメってことは書いてないように思います。

> 2.プラスの記号は省略してもいいようですが,それでいいでしょうか。

 たしかにプラス記号は省略しても大丈夫です。仕様としてありとさせていただ
きます。

> 3.秒の指定は無効のようですが,これは仕様でしょうか。

 秒の部分は見てないですけども、せっかくなので次バーションで秒も指定出来
るようにさせていただきます。

 "+0.0.0.10"とか指定すると、+10秒って意味にします。

> 5.例題の説明に
>  $date = dllfuncstr("ShiftDate", $date, "月");    // 先週の月曜日
> とありますが,これは「その週の月曜日」あるいは「パラメータ1の属する週の月曜
> 日」ではないでしょうか。

 たしかに「その週の月曜日」のようでした。コメントの間違いでした。

 さらに、この件でソースコード見直しをしたら、そもそも曜日の補正をする用
の計算が間違ってて、パラメータ1で指定された週じゃなくて、今現在の日時の
週を基準に補正量を計算するようなバグがありました。なのでパラメータ1に今
日の日付以外を指定されたら計算ミスになってました。

 これまた修正させていただきます。

>  マクロを公開する場合に,「秀丸エディタの正規のユーザーで秀丸メールをインス
> トールしていない人は,tkinfo.dll だけをマクロ用のフォルダにコピーできま
> す。」

 秀丸エディタのライセンスがあれば秀丸メールもセットで使えるので、しいて
そういうユーザー様がtkinfo.dllだけを抽出して使うことにはライセンス的には
問題は無いし、そういう文章を掲載すること自体にも問題は無いです。

[ ]
RE:07682 ShiftDate関数(TKInfo.dll)にNo.07683
秀まるお さん 13/01/25 11:24
 
 ShiftDateの中での処理ですが、とりあえず次のβ版で、
FileTimeToSystemTimeの変換関数でエラーが返ったらエラーメッセージを表示し
て""を返すようにしてみます。現状ではエラーかどうか見てないので、エラーに
なった場合は不定な値が返ってしまってるようでした。

[ ]
RE:07683 ShiftDate関数(TKInfo.dll)にNo.07685
秀まるお さん 13/01/25 13:44
 
 もう1つありました。

 実はShiftDate関数のパラメータ2には、文字列として"-9999"のようなのを指
定出来るのとは別に、数値で-9999と指定してもうまく動作するようにしていま
す。ですが、その数値として指定出来る範囲に制限がありました。

 パラメータ2が数値なのか文字列なのか判定するのに、

    if( (INT_PTR)pszShift < 0x10000 && (INT_PTR)pszShift > -(0x10000) ) {
        数値の場合の処理…
    } else {
        文字列の場合の処理…
    }

 のようになってまして、65536以上または-65536以下の値は指定出来ないこと
になります。

 元々ShiftDate関数はテンプレートから呼び出して使うように作った関数であ
るために、基本的には文字列型でパラメータ指定してもらわないとダメになりま
す。

 これも一応ヘルプに追加させていただきます。

[ ]
RE:07685 ShiftDate関数(TKInfo.dll)にNo.07686
山紫水明 さん 13/01/25 19:56
 
 秀まるおさん,

 どうもShiftDate関数ではなく,FormatDate関数の方に問題があるようです。
 で次のマクロで調べてみました。 β18+Windows Vista です。

//---------------------------------------------------------------
$t = input("遡及日数");
$t = "-" + $t;
$s = dllfuncstr("ShiftDate", dllfuncstr("CurrentDate"), $t);
$s1 = dllfuncstr( "FormatDate", $s, "YYYY/MM/DD(W)");
$s2 = dllfuncstr( "FormatDate", $s, "平成Y年M月D日(W)");
//message $t + "\n" + $s + "\n" + $s1 + "\n" + $s2;
insert $t + "\n" + $s + "\n" + $s1 + "\n" + $s2 + "\n-----------------\n";
//---------------------------------------------------------------

結果の一部は次のとおりです。

-8790
Sun, 01 Jan 1989 14:30:24 +0900
1989/01/01(日)
平成1年1月1日(日)
1989年(昭和64年)1月8日に昭和→平成 ですので,
昭和64年1月1日(日) となるべきところです
なお,1年は通常元年と書きますが,そこまでは・・・。
------------------
-31443
Sat, 25 Dec 1926 14:41:29 +0900
1926/12/25(土)
昭和1年12月25日(土)
------------------
-31444
Fri, 24 Dec 1926 14:42:36 +0900
1926/12/24(金)
昭和1年12月24日(金)
これも元号変更の関係で
大正15年12月24日(金)
となるべきところです。
------------------
-32000
Tue, 16 Jun 1925 14:46:54 +0900
1925/06/16(火)
昭和0年6月16日(火) ?
------------------
-33000
Wed, 20 Sep 1922 14:47:08 +0900
1922/09/20(水)
昭和65533年9月20日(水) → ???
------------------
-41297
Mon, 01 Jan 1900 14:50:30 +0900
1900/01/01(月) → ここまでは西暦の変換は正しいです。
昭和65511年1月1日(月)
------------------
-41298
Sun, 31 Dec 1899 14:50:05 +0900
1999/12/31(金) → ここからは西暦の変換がおかしくなります。
平成11年12月31日(金)
------------------
-100000
Sun, 12 Apr 1739 15:51:14 +0900
2039/04/12(火)
平成51年4月12日(火)
------------------
-150000
Mon, 20 May 1602 15:52:50 +0900
2002/05/20(月)
平成14年5月20日(月)
------------------
-200000
, 65535  32458 55214:30571:2430 +0900 → ???
2013/01/25(金)
平成25年1月25日(金)
------------------

元号表記については,現状のままで
 元号の変更年については不正確になる場合がある。
 昭和より前はサポートしない。
を仕様とするか,
 明治までは正しく変換する
などがあると思います。

FormatDate関数については,ShiftDate関数が実行可能な範囲までは正しく変換
して欲しいところです。

 このマクロを実行中に保護違反で異常終了しました。 dump.txt を別途お送り
します。
                          山紫水明

[ ]
RE:07686 ShiftDate関数(TKInfo.dll)にNo.07688
秀まるお さん 13/01/26 14:06
 
 いろいろ動作確認&サンプルマクロ作っていただきありがとうございます。こ
ちらでも再現出来ました。

 FormatDateですが、たしかに1899年以下はうまく処理出来てませんでした。こ
れは、実はDate:ヘッダを解釈する処理はいろいろイレギュラーケースに対応す
る用の処理が入っていて、4桁の数字があったとしても、それが年号的におかし
い場合は無視するような処理がありました。その年号チェックが、実は1900以上
かどうかになっていました。とりあえず1601年以降はうまく年号として解釈する
ように修正させていただきます。

 あと、FormatDateでの「昭和、平成」の所での明治、大正のサポートもついで
にやってみます。(メールとしてはありえないので想定外でしたが)

 保護違反で落ちてしまう件も再現出来ました。マクロを実行して出てくる日数
に9999999とか、極端な値を指定したら再現出来ました。この場合は「ShiftDate
で日付がオーバーフローまたはアンダーフローしました」のエラーを出すように
しつつ、落ちてる直接の処理についても安全対策を入れるように修正させていた
だきます。

[ ]
RE:07688 FormatDate関数(TKInfo.dll)にNo.07695
山紫水明 さん 13/01/28 22:01
 
 秀まるおさん,

β29 試してみました。

>とりあえず1601年以降はうまく年号として解釈するように修正させていただき
>ます。
 これは正しく動いているようです。

> あと、FormatDateでの「昭和、平成」の所での明治、大正のサポートもつい
>でにやってみます。(メールとしてはありえないので想定外でしたが)

 たしかに秀丸メールとしては必要ないですよね。少し無理言って対応していた
だいて恐縮です。ただ,秀丸エディタ側のDLLにこの種の関数がないのであり
がたいです。
 前回のマクロで実験してみました。細かいところですが,元号変更年で若干の
問題が残っているようです。

------------------
-8790
Wed, 04 Jan 1989 20:01:25 +0900
1989/01/04(水)
平成1年1月4日(水)
  昭和64年1月4日(水) となるべきところ
------------------
-31447
Fri, 24 Dec 1926 20:04:10 +0900
1926/12/24(金)
昭和1年12月24日(金)
  大正15年12月24日(金) となるべきところ
------------------
-36730
Sun, 07 Jul 1912 20:18:34 +0900
1912/07/07(日)
大正1年7月7日(日)
  明治45年7月7日(日)となるべきところ
------------------
-36950
Thu, 30 Nov 1911 20:23:28 +0900
1911/11/30(木)
大正0年11月30日(木)
 明治44年11月30日(木) となるべきところ
------------------

>「ShiftDate
>で日付がオーバーフローまたはアンダーフローしました」のエラーを出すよう
>にしつつ、落ちてる直接の処理についても安全対策を入れるように修正させて
>いただきます。

 こちらも今のところ落ちることはありません。

 別件で確認ですが,次のようなマクロで試して見ました。

$s1 = "Mon, 28 Jan 2013 20:36:57 +0900";
$s2 = "Mon, 28 Jan 2013 20:36:57";  //時差省略
$s3 = "28 Jan 2013 20:36:57";       //曜日省略
$s4 = "Sun, 28 Jan 2013 20:36:57";  //誤った曜日
$t1 = dllfuncstr( "FormatDate", $s1, "YYYY/MM/DD(W)" );
$t2 = dllfuncstr( "FormatDate", $s2, "YYYY/MM/DD(W)" );
$t3 = dllfuncstr( "FormatDate", $s3, "YYYY/MM/DD(W)" );
$t4 = dllfuncstr( "FormatDate", $s4, "YYYY/MM/DD(W)" );
message $t1;
message $t2;
message $t3;
message $t4;

 いずれも同じ結果です。
 パラメータの文字列の中で,タイムゾーンや曜日は必須ではないということで
いいのでしょうか。

                          山紫水明

[ ]
RE:07695 FormatDate関数(TKInfo.dll)にNo.07697
秀まるお さん 13/01/29 11:02
 
 毎度、詰めが甘くてすみません。

 平成元年/昭和64年については、検索してみたら何月何日かで分けないとダメ
なのですね。

 http://oshiete.goo.ne.jp/qa/651208.html

 そのようなロジックに修正してみます。大正0年の件はバグでした。

 あと、

>  パラメータの文字列の中で,タイムゾーンや曜日は必須ではないということで
> いいのでしょうか。

 曜日はまったく見てません。

 タイムゾーンは、あれば見ますが、無ければ今現在のパソコンのタイムゾーン
と同じと解釈するようになってたと思います。

 FormatDate関数やShiftDate関数でDate:ヘッダ相当の文字列を解釈する処理は、
秀丸メールでのDate:ヘッダを解釈する処理そのままなのですけども、Date:ヘッ
ダの中身は、いろいろイレギュラーケースがあって、そういうイレギュラーケー
スであっても可能な限り正しい日時で解釈出来るようにしています。また、何か
エラーがあったとしても、メールを受信してる最中にエラーメッセージを出して
止める訳にはいかないので、適当に解釈して何らかの日付を返すようになってし
まってます。

--------------------------------------------------------
 一応、間違ったらいけないのでテストマクロを作って動作確認しました。その
マクロと、今現在の修正版での結果も掲載させていただきます。ついでに
「平成g」と書いた場合は1年を元年と表示するようにしました。

    loaddll "tkinfo.dll";
    $today = dllfuncstr("CurrentDate");
    $format = "YYYY E平成Y 平成Y 平成gY  M月 D日";
    $formatY = "YYYY E平成Y 平成Y 平成gY";

    $current = dllfuncstr("FormatDate", $today, $formatY );
    insert $current + "\n";
    #shift = -1;
    while(1) {
        $date = dllfuncstr("ShiftDate", $today, str(#shift) );
        $next = dllfuncstr("FormatDate", $date, $formatY );
        if( $next != $current ) {
            #shiftPrev = #shift + 1;
            $datePrev = dllfuncstr("ShiftDate", $today, str(#shiftPrev) );
            $ins1 = dllfuncstr("FormatDate", $datePrev, $format );
            $ins1 = $ins1 + leftstr( "                   "
                           , 35 - strlen($ins1) );
            insert $ins1 + dllfuncstr("FormatDate", $date, $format ) + "\n";
            $current = $next;
        }
        if( val(leftstr( $current, 4 )) < 1700 ) {
            break;
        }
        #shift = #shift - 1;
    }
    message "終了";

-----------------------------------------------------------------
2013 H25 平成25 平成25
2013 H25 平成25 平成25  1月 1日    2012 H24 平成24 平成24 12月31日


1990 H2 平成2 平成2  1月 1日       1989 H1 平成1 平成元 12月31日
1989 H1 平成1 平成元  1月 8日      1989 S64 昭和64 昭和64  1月 7日
1989 S64 昭和64 昭和64  1月 1日    1988 S63 昭和63 昭和63 12月31日


1926 S1 昭和1 昭和元 11月25日      1926 T15 大正15 大正15 11月24日
1926 T15 大正15 大正15  1月 1日    1925 T14 大正14 大正14 12月31日


1913 T2 大正2 大正2  1月 1日       1912 T1 大正1 大正元 12月31日
1912 T1 大正1 大正元  7月30日      1912 M45 明治45 明治45  7月29日
1912 M45 明治45 明治45  1月 1日    1911 M44 明治44 明治44 12月31日
1869 M2 明治2 明治2  1月 1日       1868 M1 明治1 明治元 12月31日
1868 M1 明治1 明治元  9月 8日      1868 1868 1868 1868  9月 7日
1868 1868 1868 1868  1月 1日       1867 1867 1867 1867 12月31日



[ ]
RE:07697 FormatDate関数(TKInfo.dll)にNo.07704
山紫水明 さん 13/01/29 17:40
 
 秀まるおさん,

> 曜日はまったく見てません。
> タイムゾーンは、あれば見ますが、無ければ今現在のパソコンのタイムゾー
>ンと同じと解釈するようになってたと思います。

 なるほど,了解しました。

> 一応、間違ったらいけないのでテストマクロを作って動作確認しました。
>-----------------------------------------------------------------
>1989 H1 平成1 平成元  1月 8日      1989 S64 昭和64 昭和64  1月 7日
>1926 S1 昭和1 昭和元 11月25日      1926 T15 大正15 大正15 11月24日
>1912 T1 大正1 大正元  7月30日      1912 M45 明治45 明治45  7月29日

昭和→平成,明治→大正についてはこれでいいですが,大正→昭和の改元は
12月25日のはずです。

 こちらでもテストマクロをそのまま貼り付けて実行してみました。
 はじめの5行だけをそのままあげてみますと,

2013 H25 平成25 平成g25
2013 H25 平成25 平成g25  1月 1日   2012 H24 平成24 平成g24 12月31日
2012 H24 平成24 平成g24  1月 1日   2011 H23 平成23 平成g23 12月31日
2011 H23 平成23 平成g23  1月 1日   2010 H22 平成22 平成g22 12月31日
2010 H22 平成22 平成g22  1月 1日   2009 H21 平成21 平成g21 12月31日

となります。修正前の版なので「平成g」となるのはともかくとして,なぜか1
年おきに書き出さていれます。マクロは1日ずつシフト日数が増えていると思い
ますが?

                          山紫水明

[ ]
RE:07704 FormatDate関数(TKInfo.dll)にNo.07707
秀まるお さん 13/01/29 18:26
 
 V6.10β30をアップロードしてしまったのですが、たしかに、

> 昭和→平成,明治→大正についてはこれでいいですが,大正→昭和の改元は
> 12月25日のはずです。

 の所を間違ってしまってました。毎度自分が情けないです。

 また修正させていただきます。

> となります。修正前の版なので「平成g」となるのはともかくとして,なぜか1
> 年おきに書き出さていれます。マクロは1日ずつシフト日数が増えていると思い
> ますが?

 マクロは、たしかにシフトするのは1日毎ですが、1日毎に1行ずつ出力した
ら膨大な量になってしまうので、「年が変化したら、その変わった日の前後2日
分を出力する」みたいな処理をしています。

 $formatYで年の部分だけ計算させて、それが違ってたらって処理にしています。

[ ]
RE:07707 FormatDate関数(TKInfo.dll)にNo.07711
山紫水明 さん 13/01/29 21:17
 
 秀まるおさん,

> マクロは、たしかにシフトするのは1日毎ですが、1日毎に1行ずつ出力した
>ら膨大な量になってしまうので、「年が変化したら、その変わった日の前後2日
>分を出力する」みたいな処理をしています。
> $formatYで年の部分だけ計算させて、それが違ってたらって処理にしています。

 マクロをよく見たらそうなっていました。失礼しました。
 β29で実行したので,そこのところは1月1日と12月31日のところだけ出力されて
いて気がつきませんでした。
 β30で実行したら,年の途中の改元の前後が書き出されていました。大正→昭和の
日付以外は問題ないと思います。

                          山紫水明

[ ]