〜 タイム 〜
基準日から指定日後の日付を取得

特定の日付を基準に、指定日数後の日付を求めるサンプルです。
コレを使うことで「○年△月□日の☆日後は●年▲月■日である」と求められる様になります。
間に2月を挟んでいる場合は閏年のチェックも行わなければなりませんが、
閏年かのチェックにはコチラと違って#defineマクロを使用しています。
コレにより、HSP2でも関数形式に記述することができますが、
文字列中においては、カッコを使用しての計算ができず、数式の中だけしか使用できません。
閏年の判定結果を文字列内にも入れる場合、一旦変数に代入するようにしてください。
基準日を現在と仮定すると、プラスの値は未来の日付、マイナスの値は過去の日付にすることが出来ます。
単純に値を加減算しているだけなので、例えば「100万日前」を指定すれば不正なマイナス年となります。
また、指定日数の絶対的な大きさに比例して処理時間が掛ってしまうので、
「1億日後」を1回取得するだけでもマシンによって3〜4秒は掛ってしまいます。
	

dateinit 基準年, 基準月, 基準日
基準年日付計算用の基準とする年を指定する。
基準月日付計算用の基準とする月を指定する。
基準日日付計算用の基準とする日を指定する。

adddays 受取先配列, 日数
受取先配列基準日から指定日数分を加減した日付の受取先配列を指定する。
要素0には演算後の年、要素1には演算後の月、要素2には演算後の日がセットされる。
日数加算または減算する日数を指定する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#define global ctype leapchk(%1 = 1900) ((%1 \ 400 = 0) | ((%1 \ 4 = 0) & (%1 \ 100 ! 0)))
#module
#deffunc dateinit int, int, int
	mref year, 0 : mref month, 1 : mref day, 2
	days = 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
	kijun = year, month, day
	if year = 0 : kijun = 1900
	return

#deffunc adddays val, int
	if kijun = 0 : dateinit
	mref data, 48 : mref day, 1
	data = kijun, kijun.1, kijun.2
	if day < 0 {
		repeat -day / days
			if day + days + leapchk(data) <= 0 : break
			day += days + leapchk(data)
			data--
		loop
		repeat
			if data.2 + day > 0 : break
			if data.1 > 1 : data.1-- : else : data-- : data.1 = 12
			i = data.1
			day += (days.i + (data.1 = 2 & leapchk(data)))
		loop
		data.2 += day
	} else {
		repeat day / days
			if day - days + leapchk(data) <= 0 : break
			day -= (days + leapchk(data))
			data++
		loop
		if data.1 > 2 & (leapchk(data) = 0) : day++
		repeat
			i = data.1
			if data.2 + day <= (days.i + (data.1 = 2 & leapchk(data))) : break
			day -= (days.i + (data.1 = 2 & leapchk(data)))
			if data.1 < 12 : data.1++ : else : data++ : data.1 = 1
		loop
		data.2 += day
	}
	return
#global

	date = 2008, 3, 1
	mes "基準:" + date +"年" + date.1 + "月" + date.2 + "日"
	dateinit date.0, date.1, date.2
	randomize 3
	repeat 20
		rnd r.0, 10000 : rnd r.1, 10000 : r -= r.1
		adddays date, r
		pos  10, cnt * 20 + 30 : mes "" + r + "日後:"
		pos 100, cnt * 20 + 30 : mes "" + date +"年" + date.1 + "月" + date.2 + "日"
	loop
	stop

dateinit 基準年, 基準月, 基準日
基準年日付計算用の基準とする年を指定する。
基準月日付計算用の基準とする月を指定する。
基準日日付計算用の基準とする日を指定する。

adddays 受取先配列, 日数
受取先配列基準日から指定日数分を加減した日付の受取先配列を指定する。
要素0には演算後の年、要素1には演算後の月、要素2には演算後の日がセットされる。
日数加算または減算する日数を指定する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#define global ctype leapchk(%1 = 1900) ((%1 \ 400 = 0) | ((%1 \ 4 = 0) & (%1 \ 100 ! 0)))
#module
#deffunc dateinit int year, int month, int day
	days = 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
	kijun = year, month, day
	if year = 0 : kijun = 1900
	return

#deffunc adddays array data, int day, local i
	if kijun = 0 : dateinit
	i = day
	data = kijun, kijun.1, kijun.2
	if i < 0 {
		repeat -i / days
			if i + days + leapchk(data) <= 0 : break
			i += days + leapchk(data)
			data--
		loop
		repeat
			if data.2 + i > 0 : break
			if data.1 > 1 : data.1-- : else : data-- : data.1 = 12
			i += days(data.1) + (data.1 = 2 & leapchk(data))
		loop
		data.2 += i
	} else {
		repeat i / days
			if i - days + leapchk(data) <= 0 : break
			i -= days + leapchk(data)
			data++
		loop
		if data.1 > 2 & leapchk(data) = 0 : i++
		repeat
			if data.2 + i <= days(data.1) + (data.1 = 2 & leapchk(data)) : break
			i -= days(data.1) + (data.1 = 2 & leapchk(data))
			if data.1 < 12 : data.1++ : else : data++ : data.1 = 1
		loop
		data.2 += i
	}
	return
#global

	date = 2008, 2, 1
	mes "基準:" + strf("%04d年", date) + strf("%02d月", date.1) + strf("%02d日", date.2)
	dateinit date.0, date.1, date.2
	randomize
	repeat 20
		r = rnd(10000) - rnd(10000)
		adddays date, r
		pos  10, cnt * 20 + 30 : mes strf("%d日後", r)
		pos 100, cnt * 20 + 30 : mes strf("%04d年", date) + strf("%02d月", date.1) + strf("%02d日", date.2)
	loop