shithub: mc

ref: 7e02923fe7e9abd65a9b039a832ca593075f8132
dir: /lib/date/date.myr/

View raw version
use std
use "types.use"
use "zoneinfo.use"

pkg date =
	/* date i/o */
	const parse	: (d : byte[:]	-> date)
	const parsefmt	: (fmt : byte[:], d : byte[:]	-> date)
	const parsez	: (d : byte[:], tz : byte[:]	-> date)
	const fmt	: (d : date	-> byte[:])
	const fmtymd	: (d : date	-> byte[:])
	const bfmt	: (buf : byte[:], d : date	-> std.size)
	const bfmtymd	: (buf : byte[:], d : date	-> std.size)

	/* useful constructors */
	const mkdate	: (tm : std.time, tz : diff -> date)
	const now	: (tz : byte[:] -> date)
	const utcnow	: (-> date)
	const localoff	: (-> diff)
	const tzoff	: (tzname : byte[:]	-> diff)

	/* date differences */
	const add	: (d : date, dt : diff	-> date)
	const diff	: (a : date, b : date -> diff)
;;

const Unix2Julian	= 719468
const Days400y	= 365*400 + 4*25 - 3
const Days4y	= 365*4 + 1

const fmt = {d
	-> std.fmt("%04i-%02i-%02i %i:%i:%i", d.year, d.mon, d.day, d.h, d.m, d.s)
}

const fmtymd = {d
	-> std.fmt("%04i-%02i-%02i", d.year, d.mon, d.day)
}

const bfmt = {buf, d
	-> std.bfmt(buf, "%04i-%02i-%02i %i:%i:%i", d.year, d.mon, d.day, d.h, d.m, d.s)
}

const bfmtymd = {buf, d
	-> std.bfmt(buf, "%04i-%02i-%02i", d.year, d.mon, d.day)
}

const now = {tz : byte[:]
	var tm

	tm = std.now()
	-> mkdate(tm, _zoneinfo.findtzoff(tz, tm))
}

const utcnow = {
	-> mkdate(std.now(), 0)
}

const mkdate = {tm, off
	var j, y, m, d
	var t, e
	var date

	date.actual = tm
	date.tzoff = off
	tm += off castto(std.time)
	t = tm % (24*60*60*1_000_000)	/* time */
	e = tm / (24*60*60*1_000_000)	/* epoch days */


	/* microseconds, seconds, minutes, hours */
	date.us 	= (t % 1_000_000) castto(int)
	t /= 1_000_000
	date.s 	= (t % 60) castto(int)
	t /= 60
	date.m	= (t % 60) castto(int)
	t /= 60
	date.h  = t castto(int)

	/* weekday */
	date.wday = ((e + 4) % 7) castto(int)	/* the world started on Thursday */
	/*
	year, month, day: 

	Implemented according to "Algorithm 199, conversions between calendar 
	date and Julian day number", Robert G. Tantzen, Air Force Missile Development
	Center, Holloman AFB, New Mex.

	Lots of magic. Yer a wizard, 'arry.
	*/
	j = e + Unix2Julian
	y = (4 * j - 1) / Days400y
	j = 4 * j - 1 - Days400y * y
	d = j / 4
	j = (4 * d + 3) / Days4y
	d = 4 * d + 3 - Days4y * j
	d = (d + 4) / 4 ;
	m = (5 * d - 3) / 153
	d = 5 * d - 3 - 153 * m
	d = (d + 5) / 5
	y = 100 * y + j
	if m < 10
		m += 3
	else
		m -= 9 
		y++
	;;
	date.year = y castto(int)
	date.mon = m castto(int)
	date.day = (d + 1) castto(int)
	-> date
}

const ndays = {y
	if y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)
		-> 366
	else
		-> 365
	;;
}