Example #1
0
static unsigned int
__bizda_get_yday(dt_bizda_t that, dt_bizda_param_t param)
{
/* return the N-th business day in Y,
 * the meaning of ultimo will be stretched to Y-ultimo, either last year's
 * or this year's, other reference points are not yet supported
 *
 * we use the following table (days beyond 20 bdays per month (across)):
 * Mon  3  0  2   1  3  1   2  3  0   3  2  1 
 * Mon  3  1  1   rest like Tue
 * Tue  3  0  1   2  3  0   3  2  1   3  1  2 
 * Tue  3  1  1   rest like Wed
 * Wed  3  0  1   2  2  1   3  1  2   3  0  3 
 * Wed  3  0  2   rest like Thu
 * Thu  2  0  2   2  1  2   3  1  2   2  1  3 
 * Thu  2  0  3   rest like Fri
 * Fri  1  0  3   2  1  2   2  2  2   1  2  3 
 * Fri  1  1  3   rest like Sat
 * Sat  1  0  3   1  2  2   1  3  2   1  2  2 
 * Sat  1  1  3   rest like Sun
 * Sun  2  0  3   0  3  2   1  3  1   2  2  1 
 * Sun  2  1  2   rest like Mon
 * */
	struct __bdays_by_wday_s {
		unsigned int jan:2;
		unsigned int feb:2;
		unsigned int mar:2;
		unsigned int apr:2;
		unsigned int may:2;
		unsigned int jun:2;
		unsigned int jul:2;
		unsigned int aug:2;
		unsigned int sep:2;
		unsigned int oct:2;
		unsigned int nov:2;
		unsigned int dec:2;

		unsigned int feb_leap:2;
		unsigned int mar_leap:2;

		/* 4 bits left */
		unsigned int flags:4;
	};
	static struct __bdays_by_wday_s tbl[8U] = {
		{
			/* DT_MIRACLEDAY */
			0, 0, 0,  0, 0, 0,  0, 0, 0,  0, 0, 0,  0, 0, 0
		}, {
			/* DT_MONDAY */
			3, 0, 2,  1, 3, 1,  2, 3, 0,  3, 2, 1,  1, 1, 0
		}, {
			/* DT_TUESDAY */
			3, 0, 1,  2, 3, 0,  3, 2, 1,  3, 1, 2,  1, 1, 0
		}, {
			/* DT_WEDNESDAY */
			3, 0, 1,  2, 2, 1,  3, 1, 2,  3, 0, 3,  0, 2, 0
		}, {
			/* DT_THURSDAY */
			2, 0, 2,  2, 1, 2,  3, 1, 2,  2, 1, 3,  0, 3, 0
		}, {
			/* DT_FRIDAY */
			1, 0, 3,  2, 1, 2,  2, 2, 2,  1, 2, 3,  1, 3, 0
		}, {
			/* DT_SATURDAY */
			1, 0, 3,  1, 2, 2,  1, 3, 2,  1, 2, 2,  1, 3, 0
		}, {
			/* DT_SUNDAY */
			2, 0, 3,  0, 3, 2,  1, 3, 1,  2, 2, 1,  1, 2, 0
		},
	};
	dt_dow_t j01wd;
	unsigned int y = that.y;
	unsigned int m = that.m;
	unsigned int accum = 0;

	if (UNLIKELY(param.ref != BIZDA_ULTIMO)) {
		return 0;
	}
	j01wd = __get_jan01_wday(that.y);

	if (LIKELY(!__leapp(y))) {
		union {
			uint32_t u;
			uint32_t lu:2;
			struct __bdays_by_wday_s s;
		} page = {
			.s = tbl[j01wd],
		};
		for (unsigned int i = 0; i < m - 1; i++) {
			accum += page.lu;
#if BYTE_ORDER == BIG_ENDIAN
			page.u <<= 2;
#elif BYTE_ORDER == LITTLE_ENDIAN
			page.u >>= 2;
#else
# warning unknown byte order
#endif	/* BYTE_ORDER */
		}
	} else if (m > 1) {
Example #2
0
DEFUN unsigned int
__ymcw_get_yday(dt_ymcw_t that)
{
/* return the N-th W-day in Y, this is equivalent with 8601's Y-W-D calendar
 * where W is the week of the year and D the day in the week */
/* if a year starts on W, then it's
 * 5 Ws in jan
 * 4 Ws in feb
 * 4 Ws in mar
 * 5 Ws in apr
 * 4 Ws in may
 * 4 Ws in jun
 * 5 Ws in jul
 * 4 Ws in aug
 * 4 + leap Ws in sep
 * 5 - leap Ws in oct
 * 4 Ws in nov
 * 5 Ws in dec,
 * so go back to the last W, and compute its number instead
 *
 * Here's the full schema:
 * For W+0
 * 5 4 4 5 4 4  5 4 4 5 4 5  non-leap
 * 5 4 4 5 4 4  5 4 5 4 4 5  leap  flip9
 *
 * For W+1
 * 5 4 4 4 5 4  5 4 4 5 4 4  non-leap
 * 5 4 4 5 4 4  5 4 4 5 4 5  leap  flip4  flip12
 *
 * For W+2
 * 5 4 4 4 5 4  4 5 4 5 4 4  non-leap
 * 5 4 4 4 5 4  5 4 4 5 4 4  leap  flip7
 *
 * For W+3
 * 4 4 5 4 5 4  4 5 4 4 5 4  non-leap
 * 4 5 4 4 5 4  4 5 4 5 4 4  leap  flip2  flip10
 *
 * For W+4
 * 4 4 5 4 4 5  4 5 4 4 5 4  non-leap
 * 4 4 5 4 5 4  4 5 4 4 5 4  leap  flip5
 *
 * For W+5
 * 4 4 5 4 4 5  4 4 5 4 4 5  non-leap
 * 4 4 5 4 4 5  4 5 4 4 5 4  leap  flip8  flip11
 *
 * For W+6
 * 4 4 4 5 4 4  5 4 5 4 4 5  non-leap
 * 4 4 5 4 4 5  4 4 5 4 4 5  leap  flip3  flip6
 *
 * flipN denotes which month in a leap year becomes 5 where the
 * month in the non-leap year equivalent has value 4.
 *
 * The flips for W+1 W+2, W+4, W+5, W+6 can be presented through
 * non-leap rules:
 *
 * 544544544545544544544545
 * 544544545445544544545445
 *
 * 544454544544544454544544
 * 544544544545544544544545 = non-leap W+0
 *
 * 544454454544544454454544
 * 544454544544544454544544 = non-leap W+1
 *
 * 445454454454445454454454
 * 454454454544454454454544
 *
 * 445445454454445445454454
 * 445454454454445454454454 = non-leap W+3
 *
 * 445445445445445445445445
 * 445445454454445445454454 = non-leap W+4
 *
 * 444544545445444544545445
 * 445445445445445445445445 = non-leap W+5
 */
	static uint8_t ycum[][12] = {
		{
			/* W+0 */
			0, 5, 9, 13, 18, 22, 26,  31, 35, 39, 44, 48, /*53*/
		}, {
			/* W+1 */
			0, 5, 9, 13, 17, 22, 26,  31, 35, 39, 44, 48, /*52*/
		}, {
			/* W+2 */
			0, 5, 9, 13, 17, 22, 26,  30, 35, 39, 44, 48, /*52*/
		}, {
			/* W+3 */
			0, 4, 8, 13, 17, 22, 26,  30, 35, 39, 43, 48, /*52*/
		}, {
			/* W+4 */
			0, 4, 8, 13, 17, 21, 26,  30, 35, 39, 43, 48, /*52*/
		}, {
			/* W+5 */
			0, 4, 8, 13, 17, 21, 26,  30, 34, 39, 43, 47, /*52*/
		}, {
			/* W+6 */
			0, 4, 8, 12, 17, 21, 25,  30, 34, 39, 43, 47, /*52*/
		}, {
			/* leap-year rule W+0 */
			0, 5, 9, 13, 18, 22, 26,  31, 35, 40, 44, 48, /*53*/
			/* leap-year rule W+3 = W+0 + 1mo + 4 */
		},
	};
	dt_dow_t j01w = __get_jan01_wday(that.y);
	unsigned int diff = j01w <= that.w ? that.w - j01w : that.w + 7 - j01w;

	if (UNLIKELY(__leapp(that.y))) {
		switch (diff) {
		case 3:
			if (UNLIKELY(that.m < 2)) {
				return that.c;
			}
			return that.c + (ycum[7])[that.m - 2] + 4;
		case 0:
			return that.c + (ycum[7])[that.m - 1];
		default:
		case 1:
		case 2:
		case 4:
		case 5:
		case 6:
			diff--;
			break;
		}
	}
	return that.c + (ycum[diff])[that.m - 1];
}