日付マジック2

   
--------------------- 日付マジック2 --------------------------


はじまり、はじまり~。


<再開!>
C言語等ではこんなもんかな?

<ひえぇ~~! コレって本文よりも長くない?>
そうだね。まともに計算するとこのくらいかな?

<こんなのヤダ!>
子供か!・・・ こんな時はアレを使うしか。

<アレですか?>
アレです。

<あれ? アレってなんだっけか?>
長い、面倒、難しいと来れば?

<連想配列~~・・・こっ、この局面で使うのかよ?>
しかも逆順上書き技! それに加えて、

①ダブルdim設定。
②条件replace上書き。
③Gettimeで日付妥当性チェック。

などの新・小技を織り込んで見ました。
<何だかんだ、言いながら作ってんじゃん!>
納得がいかなくって・・・

<実行してみて?・・・代わり映えしないね。 入力はっと・・・あれ?>
<アレレ? ちゃんとハネくれるよコレ!! スゴ!!>
最低限のチェックはつけたよ。

<てかほぼ完璧じゃない? 変な入力できないよ。"00"とか "-1"までハネテクレル>
何を入力してるんだか。

<っじゃあ50行くらいになったかね?>
そんなには、ならないよ。UWSCでもIsDate関数が使えるといいのだが・・・

<ウンチクはいい! 結局何行?>
今回は、行数優先で10行です。

<冗談だよね?>
マジです。

<ってことは最初の難行9行もマジだったわけ?>
はい。

<はいはい証拠を見せて。 この目で見るまで信じるもんか!! この手の冗談はぁ>


hashtbl day
dim 納期 = replace(format(STRCONV( INPUT("納期"), SC_HALFWIDTH), 6), " ","0"), 納期日 = copy(納期, 5, 2), 仮納期年月日
for i = 60 to 1 step -1
  Gettime(i)
  day[G_TIME_DD2] = G_TIME_YY2 + G_TIME_MM2 + G_TIME_DD2
next
if day[納期日, HASH_EXISTS] then 仮納期年月日 = day[納期日] else exit
dim 納期月 = replace(copy(納期, 3, 2), "00", copy(仮納期年月日, 3, 2)), 納期年 = replace(copy(納期, 1, 2), "00", copy(仮納期年月日, 1, 2)), 納期年月日 = 納期年 + 納期月 + 納期日
if (val(納期月) < 1) or (val(納期月) > 12) then exit else gettime(val(納期日)-1, "20" + 納期年 + 納期月 + "01")
if G_TIME_DD2 = 納期日 then msgbox("納期年月日 : " + 納期年月日) else msgbox("日付が存在しません")


<・・・冗談抜きのマジですか? たったコレだけでアレだけのチェックをやってのけるのぉ~~?>
<ちょっと、ごちゃごちゃしてるけど階層が深くないから・・・ってか1階層しかない! ってかループだけぇ!>

<dim宣言の中にナニ思いっきり突っ込んでんよアンタはぁ、しかも2回!>
<連想配列も逆からブッコン出るしぃ>

<しっかしまあ、よくもこんだけ無茶をしたもんだ! ??? アンタがLinersってこと忘れてたぁ。>
<コレがアンタにとっては、自然なのよね?>
まあね。


おしまい。



-----------------------------------------------------------------------------------------------

提供は: 日付マジック.txt = Liners でした。

-----------------------------------------------------------------------------------------------
次の日にちを算出 sen    
    日にちだけでも月日でも納期をキチンと入力させたくて、下記の様なのを考えてみました。「15」と入力すると、今日から後なので当然「110515」と入力させたいのですが、長々となりました。もう少しスマートなのはないでしょうか?

Gettime()
今日 = G_TIME_YY2 + G_TIME_MM2 + G_TIME_DD2
今日年 = G_TIME_YY2
今日月 = G_TIME_MM2
今日日 = G_TIME_DD2
納期年 = 0
納期月 = 0
納期日 = 0
納期 = INPUT("納期")
納期 = STRCONV( 納期,SC_HALFWIDTH)// 半角文字
ifb length(納期) = 1 then //日にちだけ入力
納期日 = "0"+ 納期
for i=1 to 60
Gettime(i)
ifb 納期日 = G_TIME_DD2 then
納期月 = G_TIME_MM2
納期年 = G_TIME_YY2
Sleep(0.1)
break
endif
next
納期年月日 = 納期年 + 納期月 + 納期日
elseif length(納期) = 2 then
納期日 = copy(納期,1,2)
for i=1 to 60
Gettime(i)
ifb 納期日 = G_TIME_DD2 then
納期月 = G_TIME_MM2
納期年 = G_TIME_YY2
Sleep(0.1)
break
endif
next
納期年月日 = 納期年 + 納期月 + 納期日
elseif length(納期) = 3 then
納期月 = "0"+ copy(納期,1,1)
納期日 = copy(納期,2,2)
for i=1 to 60
Gettime(i)
ifb 納期日 = G_TIME_DD2 then
納期年 = G_TIME_YY2
Sleep(0.1)
break
endif
next
納期年月日 = 納期年 + 納期月 + 納期日
elseif length(納期) = 4 then
納期月 = copy(納期,1,2)
納期日 = copy(納期,3,2)
for i=1 to 60
Gettime(i)
ifb 納期日 = G_TIME_DD2 then
納期年 = G_TIME_YY2
Sleep(0.1)
break
endif
next
納期年月日 = 納期年 + 納期月 + 納期日
elseif length(納期) = 5 then
納期年 = "0"+ copy(納期,1,1)
納期月 = copy(納期,2,2)
納期日 = copy(納期,4,2)
納期年月日 = 納期年 + 納期月 + 納期日
elseif length(納期) = 6 then
納期年 = copy(納期,1,2)
納期月 = copy(納期,3,2)
納期日 = copy(納期,5,2)
納期年月日 = 納期年 + 納期月 + 納期日
endif

PRINT "納期年月日"+納期年月日
DATE:2011/5/7(Sat) 01:46 No.3614    
   
    RE:次の日にちを算出 Liners    
   
    へえ~・・・こんな考え方もあるんだ。向こう60日を先読みして日付を補完するのか。・・・現場ならでの発想?でも入力チェックは厳しい方がよいのでは?
無駄な変数や、同じ場所をまとめて短くすることは出来るが、コレは大きなIF文ブロックであり、構造ごと考え直した方が得策かと思います。

とりあえず、 納期 = replace(format(STRCONV( INPUT("納期"), SC_HALFWIDTH), 6), " ","0") で0付の6桁として2桁づつ分割。
各 日、月、年ごとに処理すれば、行数は半減します。

しかし、私としてはやはり、入力チェックを厳しくして行数が増えても、せめて "45","1302","231" は、はねてもらいたい。
DATE:2011/5/7(Sat) 13:50    



-----------------------------------------------------------------------------------------------
    日にちの計算 sen    
    納期に対して1日前の作業日を計算したいのですが、土日祝祭日あり、出勤の土曜日ありでうまくいきません。別にcsvで休みの日をもでば良いような気がしますが、教えてもらえませんでしょうか。

(例)
納期 110509
作業日 110506←5/7と5/8は休みなので飛ばす。

納期 110516
作業日 110514←5/15は休みなので飛ばす。


休み.csv
110507
110508
110515
DATE:2011/5/3(Tue) 19:21 No.3606    
   
    RE:日にちの計算 Liners    
   
    不規則な休日なら休日データを別途用意して、配列か文字列に入れて検索するしかないでしょう。方法としては
①配列に入れループで回す。
②文字列に入れて番兵を立てて検索
③連想配列に入れて検索

上記に加え、連休もありえるので
A:ループで休日でなくなるまで回す
B:関数化し再帰を利用する

上記の組み合わせか、力ずくで全ての日付に対する作業日表を作っておくなどです。
もちろん納期の前日を4桁の文字列にする事が必要です。
うまくいかないスクリプトを掲示してください。

当方も ② * B: の組み合わせで作成してみます。
DATE:2011/5/3(Tue) 21:36    
   
    RE:日にちの計算 sen    
   
    恥ずかしながら、こんなのしか思いつかないのですが、
これだと、毎日すべての日にちを入力しないといけないので大変な事があり、日々の仕事が増加するのと、誤入力が発生しそうです。
実際には、業者によって日曜日積み込みする業者もあり、そうなると列も
右にドンドンと増加します。(対応は簡単)
駄目な点は、上記の事とともに、
・日にちを文字列で扱っているのは、どうなのか?
やはり、「-1」で前日を計算できないは、プログラムではないかも?
・365日を全部入力すると、他のパソコンで使用しずらい点があります。
休みだけとかをcsvに一年分ゴッソリ入力しておければ、簡単で扱い安いのにという思いがあります。

----------------------
作業日=0
納期="110522"

積込台帳 = fopen("納期作業日.csv")
For 回数 = 1 to fget(積込台帳,-1)
ifb 納期 = fget(積込台帳,回数,1) then
作業日 = fget(積込台帳,回数,2)
break
endif
next
fclose(積込台帳)

print 納期
print 作業日

----------------------
納期作業日.csv
----------------------
納期,作業日,
110507,110506,
110508,110506,日曜日
110509,110508,
110510,110509,
110511,110510,
110512,110511,
110513,110512,
110514,110512,
110515,110514,日曜日
110516,110515,
110517,110516,
110518,110517,
110519,110518,
110520,110519,
110521,110520,土曜休み
110522,110520,日曜日

    RE:日にちの計算 Liners    
   
    そうでしたか。てっきり連休処理で躓いているのかと思ってました。

>日々の仕事が増加するのと、誤入力が発生しそうです。
>365日を全部入力すると、他のパソコンで使用しずらい点があります。休みだけとかをcsvに一年分ゴッソリ入力しておければ、簡単で扱い安いのにという思いがあります。
積み込みの件は、別途考慮するとして基本に戻り、単純に先の休み.csv利用してみます。

>日にちを文字列で扱っているのは、どうなのか? やはり、「-1」で前日を計算できないは、プログラムではないかも?
数値で扱っても面倒です。どの道、時間関数に頼った方が安全確実です。UWSCではGettimeを使うと前日が簡単に計算出来ます。

上記を考慮しつつ、出来るだけ簡単に(ループや配列を避けて短く)して見ました。 お役に立てるでしょうか?


public 休日 = "<#cr>" + replace(fget(fopen("休み.csv"), f_alltext), " ", "") + "<#cr>" // 休み.csvを読んで両端に改行の番兵を立てる②
納期 = "110509"
msgbox("納期 :" + 納期 + "<#cr>" + "作業日:" + 作業日(納期))

FUNCTION 作業日(納期)
  Gettime(-1, "20" + 納期) // 4桁の西暦にして1日前を計算
  Result = G_TIME_YY2 + G_TIME_MM2 + G_TIME_DD2 // 1日前を6桁の文字列に
  if pos("<#cr>" + Result + "<#cr>", 休日) then Result = 作業日(Result) // 休日データからを番兵ごと検索 見つかると自分自身を呼ぶ(再帰) B:
FEND
DATE:2011/5/4(Wed) 07:50    
   
    RE:日にちの計算 sen    
   
    ありがとうございます。
狐に摘まれた感じです。
望みの日にちが出るのにびっくりです。

肝心の番兵は全く分かりません。printで見てみると日にちの前後に改行が付いているのは分かるのですが、Linersさんの「11: 影の番兵」を久しぶりに読み直しても、以前も分からなかった事を思い出しました。

再帰も全く分かりません。「8: 再帰の再考」を読んでみても、やっぱり分かりません。
pos("<#cr>" + Result + "<#cr>", 休日)の部分右に、条件(=○○)とかは、なぜ無いのでしょうか?
また、休日が検索された時、うまい具合にその前日が表示されるのでしょうか?
もし宜しければ、御教授ください。

DATE:2011/5/5(Thu) 00:40    
   
    RE:日にちの計算 Liners    
   
    今回のように番兵を立てる目的は、互いに完全一致で検索するためです。

再帰の基本は別途じっくり学んで頂くとして、通常とは少し異なる部分を説明します。
通常なら一ランク低いパラメータを与えて自分自身を呼びますが、日付の為すぐには計算できないので、関数内に計算を内包しています。
その為一日前固定の関数です。

この為、通常なら関数内で最初に脱出判断する所が、最後になっているので少し違和感があります。
再帰はユーザー定義関数で真っ先に学ぶ、基礎の基礎ですが、これほど後になって、きれいさっぱり、完璧に忘れる技法も珍しい。

あと再帰には副作用があって無限ループに陥りやすく、呼び出しが深いとスタックオーバーになるので要注意です。

>条件(=○○)とかは、なぜ無いのでしょうか?
式に演算子がない場合、0以外が真となります。<>0 の省略形です。深い意味はありません。

>また、休日が検索された時、うまい具合にその前日が表示されるのでしょうか?
休日を検索しても、月や年をまたいでも前日が表示されるはずです。

また、完全一致全文検索なので、順番に並んでいる必要もありません。最後に休日を追加してもOKです。
DATE:2011/5/5(Thu) 03:08    
   
    RE:日にちの計算 sen    
   
    イメージ通りの動きです。ありがとうございました。
再帰は難しいですが、よく勉強したいと思います。

-----------------------------------------------------------------------------------------------