示例#1
0
文件: daisy.c 项目: cffyh/dateutils
static dt_ymd_t
__daisy_to_ymd(dt_daisy_t that)
{
	dt_daisy_t j00;
	unsigned int doy;
	unsigned int y;
	struct __md_s md;

	if (UNLIKELY(that == 0)) {
		return (dt_ymd_t){.u = 0};
	}
	y = __daisy_get_year(that);
	j00 = __jan00_daisy(y);
	doy = that - j00;
	md = __yday_get_md(y, doy);
#if defined HAVE_ANON_STRUCTS_INIT
	return (dt_ymd_t){.y = y, .m = md.m, .d = md.d};
#else  /* !HAVE_ANON_STRUCTS_INIT */
	{
		dt_ymd_t res;
		res.y = y;
		res.m = md.m;
		res.d = md.d;
		return res;
	}
#endif	/* HAVE_ANON_STRUCTS_INIT */
}

static dt_ymcw_t
__daisy_to_ymcw(dt_daisy_t that)
{
	dt_ymd_t tmp;
	unsigned int c;
	unsigned int w;

	if (UNLIKELY(that == 0)) {
		return (dt_ymcw_t){.u = 0};
	}
	tmp = __daisy_to_ymd(that);
	c = __ymd_get_count(tmp);
	w = __daisy_get_wday(that);
#if defined HAVE_ANON_STRUCTS_INIT
	return (dt_ymcw_t){.y = tmp.y, .m = tmp.m, .c = c, .w = w};
#else
	{
		dt_ymcw_t res;
		res.y = tmp.y;
		res.m = tmp.m;
		res.c = c;
		res.w = w;
		return res;
	}
#endif
}

static dt_ywd_t
__daisy_to_ywd(dt_daisy_t that)
{
	unsigned int wk = (that + 6) / 7;
	unsigned int wd = (that + 6) % 7;
	unsigned int y;
	unsigned int yw;
	dt_ywd_t res;

	/* get an estimate for the year and readjust */
	y = __daisy_get_year(that);
	/* get the cumulative week count */
	if (UNLIKELY((yw = wk - __get_cumwk(y)) == 0)) {
		y--;
		yw = __get_isowk(y);
	} else if (UNLIKELY(yw > __get_isowk(y))) {
		/* hanging over into the new year */
		yw = 1U;
		y++;
	}

	/* final assignment */
	res.y = y;
	res.c = yw;
	res.w = (wd + 1U) % 7U;
	return res;
}
#endif	/* ASPECT_CONV */


#if defined ASPECT_ADD && !defined DAISY_ASPECT_ADD_
#define DAISY_ASPECT_ADD_
#define ASPECT_GETTERS
#include "daisy.c"
#undef ASPECT_GETTERS

static dt_daisy_t
__daisy_add_d(dt_daisy_t d, int n)
{
/* add N days to D */
	d += n;
	return d;
}

static dt_daisy_t
__daisy_add_b(dt_daisy_t d, int n)
{
/* add N business days to D */
	dt_dow_t dow = __daisy_get_wday(d);
	int equ = __get_d_equiv(dow, n);
	d += equ;
	return d;
}
示例#2
0
static struct dt_d_s
dround_ddur(struct dt_d_s d, struct dt_ddur_s dur, bool nextp)
{
	switch (dur.durtyp) {
		unsigned int tgt;
		bool forw;
	case DT_DURD:
		if (dur.dv > 0) {
			tgt = dur.dv;
			forw = true;
		} else if (dur.dv < 0) {
			tgt = -dur.dv;
			forw = false;
		} else {
			/* user is an idiot */
			break;
		}

		switch (d.typ) {
			unsigned int mdays;
		case DT_YMD:
			if ((forw && d.ymd.d < tgt) ||
			    (!forw && d.ymd.d > tgt)) {
				/* no month or year adjustment */
				;
			} else if (d.ymd.d == tgt && !nextp) {
				/* we're ON the date already and no
				 * next/prev date is requested */
				;
			} else if (forw) {
				if (LIKELY(d.ymd.m < GREG_MONTHS_P_YEAR)) {
					d.ymd.m++;
				} else {
					d.ymd.m = 1;
					d.ymd.y++;
				}
			} else {
				if (UNLIKELY(--d.ymd.m < 1)) {
					d.ymd.m = GREG_MONTHS_P_YEAR;
					d.ymd.y--;
				}
			}
			/* get ultimo */
			mdays = __get_mdays(d.ymd.y, d.ymd.m);
			if (UNLIKELY(tgt > mdays)) {
				tgt = mdays;
			}
			/* final assignment */
			d.ymd.d = tgt;
			break;
		default:
			break;
		}
		break;

	case DT_DURBD:
		/* bizsis only work on bizsidurs atm */
		if (dur.dv > 0) {
			tgt = dur.dv;
			forw = true;
		} else if (dur.dv < 0) {
			tgt = -dur.dv;
			forw = false;
		} else {
			/* user is an idiot */
			break;
		}

		switch (d.typ) {
			unsigned int bdays;
		case DT_BIZDA:
			if ((forw && d.bizda.bd < tgt) ||
			    (!forw && d.bizda.bd > tgt)) {
				/* no month or year adjustment */
				;
			} else if (d.bizda.bd == tgt && !nextp) {
				/* we're ON the date already and no
				 * next/prev date is requested */
				;
			} else if (forw) {
				if (LIKELY(d.bizda.m < GREG_MONTHS_P_YEAR)) {
					d.bizda.m++;
				} else {
					d.bizda.m = 1;
					d.bizda.y++;
				}
			} else {
				if (UNLIKELY(--d.bizda.m < 1)) {
					d.bizda.m = GREG_MONTHS_P_YEAR;
					d.bizda.y--;
				}
			}
			/* get ultimo */
			bdays = __get_bdays(d.bizda.y, d.bizda.m);
			if (UNLIKELY(tgt > bdays)) {
				tgt = bdays;
			}
			/* final assignment */
			d.bizda.bd = tgt;
			break;
		default:
			break;
		}
		break;

	case DT_DURYMD:
		switch (d.typ) {
			unsigned int mdays;
		case DT_YMD:
			tgt = dur.ymd.m;
			forw = !dt_dur_neg_p(dur);

			if ((forw && d.ymd.m < tgt) ||
			    (!forw && d.ymd.m > tgt)) {
				/* no year adjustment */
				;
			} else if (d.ymd.m == tgt && !nextp) {
				/* we're IN the month already and no
				 * next/prev date is requested */
				;
			} else if (forw) {
				/* years don't wrap around */
				d.ymd.y++;
			} else {
				/* years don't wrap around */
				d.ymd.y--;
			}
			/* final assignment */
			d.ymd.m = tgt;
			/* fixup ultimo mismatches */
			mdays = __get_mdays(d.ymd.y, d.ymd.m);
			if (UNLIKELY(d.ymd.d > mdays)) {
				d.ymd.d = mdays;
			}
			break;
		default:
			break;
		}
		break;

	case DT_DURYMCW: {
		struct dt_d_s tmp;
		unsigned int wday;
		signed int diff;

		forw = !dt_dur_neg_p(dur);
		tgt = dur.ymcw.w;

		tmp = dt_dconv(DT_DAISY, d);
		wday = dt_get_wday(tmp);
		diff = (signed)tgt - (signed)wday;


		if ((forw && wday < tgt) ||
		    (!forw && wday > tgt)) {
			/* nothing to do */
			;
		} else if (wday == tgt && !nextp) {
			/* we're on WDAY already, do fuckall */
			;
		} else if (forw) {
			/* week wrap */
			diff += 7;
		} else {
			/* week wrap */
			diff -= 7;
		}

		/* final assignment */
		tmp.daisy += diff;
		d = dt_dconv(d.typ, tmp);
		break;
	}

	case DT_DURWK:
		if (dur.dv > 0) {
			tgt = dur.dv;
			forw = true;
		} else if (dur.dv < 0) {
			tgt = -dur.dv;
			forw = false;
		} else {
			/* user is an idiot */
			break;
		}

		switch (d.typ) {
			unsigned int nw;
		case DT_YWD:
			if ((forw && d.ywd.c < tgt) ||
			    (!forw && d.ywd.c > tgt)) {
				/* no year adjustment */
				;
			} else if (d.ywd.c == tgt && !nextp) {
				/* we're IN the week already and no
				 * next/prev date is requested */
				;
			} else if (forw) {
				/* years don't wrap around */
				d.ywd.y++;
			} else {
				/* years don't wrap around */
				d.ywd.y--;
			}
			/* final assignment */
			d.ywd.c = tgt;
			/* fixup ultimo mismatches */
			nw = __get_isowk(d.ywd.y);
			if (UNLIKELY(d.ywd.c > nw)) {
				d.ywd.c = nw;
			}
			break;
		default:
			break;
		}
		break;

	default:
		break;
	}
	return d;
}