示例#1
0
文件: ymcw.c 项目: aborruso/dateutils
static struct dt_ddur_s
__ymcw_diff(dt_ymcw_t d1, dt_ymcw_t d2)
{
/* compute d2 - d1 entirely in terms of ymd */
	struct dt_ddur_s res = dt_make_ddur(DT_DURYMCW, 0);
	signed int tgtd;
	signed int tgtm;
	dt_dow_t wd01, wd02;

	if (__ymcw_cmp(d1, d2) > 0) {
		dt_ymcw_t tmp = d1;
		d1 = d2;
		d2 = tmp;
		res.neg = 1;
	}

	wd01 = __get_m01_wday(d1.y, d1.m);
	if (d2.y != d1.y || d2.m != d1.m) {
		wd02 = __get_m01_wday(d2.y, d2.m);
	} else {
		wd02 = wd01;
	}

	/* first compute the difference in months Y2-M2-01 - Y1-M1-01 */
	tgtm = GREG_MONTHS_P_YEAR * (d2.y - d1.y) + (d2.m - d1.m);
	/* using the firsts of the month WD01, represent d1 and d2 as
	 * the C-th WD01 plus OFF */
	{
		unsigned int off1;
		unsigned int off2;

		off1 = __uimod(d1.w - wd01, GREG_DAYS_P_WEEK);
		off2 = __uimod(d2.w - wd02, GREG_DAYS_P_WEEK);
		tgtd = off2 - off1 + GREG_DAYS_P_WEEK * (d2.c - d1.c);
	}

	/* fixups */
	if (tgtd < (signed int)GREG_DAYS_P_WEEK && tgtm > 0) {
		/* if tgtm is 0 it remains 0 and tgtd remains negative */
		/* get the target month's mdays */
		unsigned int d2m = d2.m;
		unsigned int d2y = d2.y;

		if (--d2m < 1) {
			d2m = GREG_MONTHS_P_YEAR;
			d2y--;
		}
		tgtd += __get_mdays(d2y, d2m);
		tgtm--;
	}

	/* fill in the results */
	res.ymcw.y = tgtm / GREG_MONTHS_P_YEAR;
	res.ymcw.m = tgtm % GREG_MONTHS_P_YEAR;
	res.ymcw.c = tgtd / GREG_DAYS_P_WEEK;
	res.ymcw.w = tgtd % GREG_DAYS_P_WEEK;
	return res;
}
示例#2
0
文件: ymcw.c 项目: aborruso/dateutils
static dt_ymcw_t
__ymcw_add_b(dt_ymcw_t d, int n)
{
/* add N business days to D */
#if 0
/* trivial trait, reduce to _add_d() problem and dispatch */
	dt_dow_t wd = __ymcw_get_wday(d);
	return __ymcw_add_d(d, __get_d_equiv(wd, n));
#else
	signed int aw = n / (signed int)DUWW_BDAYS_P_WEEK;
	signed int ad = n % (signed int)DUWW_BDAYS_P_WEEK;

	if ((ad += d.w) > (signed int)DUWW_BDAYS_P_WEEK) {
		ad -= DUWW_BDAYS_P_WEEK;
		aw++;
	} else if (ad <= 0) {
		ad += DUWW_BDAYS_P_WEEK;
		aw--;
	}

	/* fixup for abswk count, m01 may be any wd */
	{
		dt_dow_t m01 = __get_m01_wday(d.y, d.m);

		if ((dt_dow_t)d.w < m01 && (dt_dow_t)ad >= m01) {
			aw++;
		} else if ((dt_dow_t)d.w >= m01 && (dt_dow_t)ad < m01) {
			aw--;
		}
	}

	d.w = (dt_dow_t)ad;
	return __ymcw_add_w(d, aw);
#endif
}
示例#3
0
文件: ymcw.c 项目: aborruso/dateutils
static dt_ymcw_t
__ymcw_add_d(dt_ymcw_t d, int n)
{
/* add N days to D
 * we reduce this to __ymcw_add_w() */
	signed int aw = n / (signed int)GREG_DAYS_P_WEEK;
	signed int ad = n % (signed int)GREG_DAYS_P_WEEK;

	if ((ad += d.w) >= (signed int)GREG_DAYS_P_WEEK) {
		ad -= GREG_DAYS_P_WEEK;
		aw++;
	} else if (ad < 0) {
		ad += GREG_DAYS_P_WEEK;
		aw--;
	}

	/* fixup for abswk count, m01 may be any wd */
	{
		dt_dow_t m01 = __get_m01_wday(d.y, d.m);

		if ((dt_dow_t)d.w < m01 && (dt_dow_t)ad >= m01) {
			aw++;
		} else if ((dt_dow_t)d.w >= m01 && (dt_dow_t)ad < m01) {
			aw--;
		}
	}

	d.w = (dt_dow_t)ad;
	return __ymcw_add_w(d, aw);
}
示例#4
0
DEFUN unsigned int
__get_bdays(unsigned int y, unsigned int m)
{
/* the 28th exists in every month, and it's exactly 20 bdays
 * away from the first, oh and it's -1 mod 7
 * then to get the number of bdays remaining in the month
 * from the number of days remaining in the month R
 * we use a multiplication table, downwards the weekday of the
 * 28th, rightwards the days in excess of the 28th
 * Miracleday is only there to make the left hand side of the
 * multiplication 3 bits wide:
 *
 * r->  0  1  2  3
 * Sun  0  1  2  3
 * Mon  0  1  2  3
 * Tue  0  1  2  3
 * Wed  0  1  2  2
 * Thu  0  1  1  1
 * Fri  0  0  0  1
 * Sat  0  0  1  2
 * Mir  0  0  0  0
 */
	unsigned int md = __get_mdays(y, m);
	unsigned int rd = (unsigned int)(md - 28U);
	dt_dow_t m01wd;
	dt_dow_t m28wd;

	/* rd should not overflow */
	assert((signed int)md - 28 >= 0);

	/* wday of the 1st and 28th */
	m01wd = __get_m01_wday(y, m);
	m28wd = (dt_dow_t)(m01wd - 1 ?: DT_SUNDAY);
	if (LIKELY(rd > 0)) {
		switch (m28wd) {
		case DT_SUNDAY:
		case DT_MONDAY:
		case DT_TUESDAY:
			return 20 + rd;
		case DT_WEDNESDAY:
			return 20 + rd - (rd == 3);
		case DT_THURSDAY:
			return 21;
		case DT_FRIDAY:
			return 20 + (rd == 3);
		case DT_SATURDAY:
			return 20 + rd - 1;
		case DT_MIRACLEDAY:
		default:
			abort();
		}
	}
	return 20U;
}
示例#5
0
static dt_dow_t
__bizda_get_wday(dt_bizda_t that)
{
	dt_dow_t wd01;
	unsigned int b;
	unsigned int magic;

	/* find first of the month first */
	wd01 = __get_m01_wday(that.y, that.m);
	b = that.bd;
	magic = (b - 1 + (wd01 < DT_SUNDAY ? wd01 : 6) - 1);
	/* now just add up bdays */
	return (dt_dow_t)((magic % DUWW_BDAYS_P_WEEK) + DT_MONDAY);
}
示例#6
0
static unsigned int
__bizda_get_mday(dt_bizda_t that)
{
	dt_dow_t wd01;
	unsigned int res;

	/* find first of the month first */
	wd01 = __get_m01_wday(that.y, that.m);

	switch (wd01) {
	case DT_MONDAY:
	case DT_TUESDAY:
	case DT_WEDNESDAY:
	case DT_THURSDAY:
	case DT_FRIDAY:
		res = 1;
		break;
	case DT_SATURDAY:
		wd01 = DT_MONDAY;
		res = 3;
		break;
	case DT_SUNDAY:
		wd01 = DT_MONDAY;
		res = 2;
		break;
	case DT_MIRACLEDAY:
	default:
		res = 0;
		break;
	}
	/* now just add up bdays */
	{
		unsigned int wk;
		unsigned int nd;
		unsigned int b = that.bd;
		unsigned int magic = (b - 1 + wd01 - 1);

		assert(b + wd01 >= 2);
		wk = magic / DUWW_BDAYS_P_WEEK;
		nd = magic % DUWW_BDAYS_P_WEEK;
		res += wk * GREG_DAYS_P_WEEK + nd - wd01 + 1;
	}
	/* fixup mdays */
	if (res > __get_mdays(that.y, that.m)) {
		res = 0;
	}
	return res;
}
示例#7
0
文件: ymcw.c 项目: aborruso/dateutils
static unsigned int
__ymcw_get_mday(dt_ymcw_t that)
{
	unsigned int wd01;
	unsigned int res;

	/* see what weekday the first of the month was*/
	wd01 = __get_m01_wday(that.y, that.m);

	/* first WD1 is 1, second WD1 is 8, third WD1 is 15, etc.
	 * so the first WDx with WDx > WD1 is on (WDx - WD1) + 1 */
	res = (that.w + GREG_DAYS_P_WEEK - wd01) % GREG_DAYS_P_WEEK + 1;
	res += GREG_DAYS_P_WEEK * (that.c - 1);
	/* not all months have a 5th X, so check for this */
	if (res > __get_mdays(that.y, that.m)) {
		 /* 5th = 4th in that case */
		res -= GREG_DAYS_P_WEEK;
	}
	return res;
}
示例#8
0
文件: ymcw.c 项目: aborruso/dateutils
DEFUN int
__ymcw_cmp(dt_ymcw_t d1, dt_ymcw_t d2)
{
	if (d1.y < d2.y) {
		return -1;
	} else if (d1.y > d2.y) {
		return 1;
	} else if (d1.m < d2.m) {
		return -1;
	} else if (d1.m > d2.m) {
		return 1;
	}

	/* we're down to counts, however, the last W of a month is always
	 * count 5, even though counting forward it would be 4 */
	if (d1.c < d2.c) {
		return -1;
	} else if (d1.c > d2.c) {
		return 1;
	}
	/* now it's up to the first of the month */
	{
		dt_dow_t wd01;
		unsigned int off1;
		unsigned int off2;

		wd01 = __get_m01_wday(d1.y, d1.m);
		/* represent cw as C-th WD01 + OFF */
		off1 = __uimod(d1.w - wd01, GREG_DAYS_P_WEEK);
		off2 = __uimod(d2.w - wd01, GREG_DAYS_P_WEEK);

		if (off1 < off2) {
			return -1;
		} else if (off1 > off2) {
			return 1;
		} else {
			return 0;
		}
	}
}
示例#9
0
文件: ymcw.c 项目: aborruso/dateutils
static __attribute__((pure)) unsigned int
__get_mcnt(unsigned int y, unsigned int m, dt_dow_t w)
{
/* get the number of weekdays W in Y-M, which is the max count
 * for a weekday W in ymcw dates in year Y and month M */
	dt_dow_t wd01 = __get_m01_wday(y, m);
	unsigned int md = __get_mdays(y, m);
	/* the maximum number of WD01s in Y-M */
	unsigned int wd01cnt = (md - 1) / GREG_DAYS_P_WEEK + 1;
	/* modulus */
	unsigned int wd01mod = (md - 1) % GREG_DAYS_P_WEEK;

	/* now the next WD01MOD days also have WD01CNT occurrences
	 * if wd01 + wd01mod exceeds the DAYS_PER_WEEK barrier wrap
	 * around by extending W to W + DAYS_PER_WEEK */
	if ((w >= wd01 && w <= wd01 + wd01mod) ||
	    (w + GREG_DAYS_P_WEEK) <= wd01 + wd01mod) {
		return wd01cnt;
	} else {
		return wd01cnt - 1;
	}
}
示例#10
0
文件: ymcw.c 项目: aborruso/dateutils
static int
__ymcw_get_bday(dt_ymcw_t that, dt_bizda_param_t bp)
{
	dt_dow_t wd01;
	int res;

	switch (that.w) {
	case DT_SUNDAY:
	case DT_SATURDAY:
		return -1;
	default:
		break;
	}
	if (bp.ab != BIZDA_AFTER || bp.ref != BIZDA_ULTIMO) {
		/* no support yet */
		return -1;
	}

	/* weekday the month started with */
	wd01 = __get_m01_wday(that.y, that.m);
	res = (signed int)(that.w - wd01) + DUWW_BDAYS_P_WEEK * (that.c) + 1;
	return res;
}