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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
|
/*** daisy.c -- guts for daisy dates
*
* Copyright (C) 2010-2024 Sebastian Freundt
*
* Author: Sebastian Freundt <freundt@ga-group.nl>
*
* This file is part of dateutils.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**/
#define ASPECT_DAISY
#include "nifty.h"
#if !defined DEFUN
# define DEFUN
#endif /* !DEFUN */
#if !defined DAISY_ASPECT_HELPERS_
#define DAISY_ASPECT_HELPERS_
#define TO_BASE(x) ((x) - DT_DAISY_BASE_YEAR)
#define TO_YEAR(x) ((x) + DT_DAISY_BASE_YEAR)
static inline __attribute__((const)) dt_daisy_t
__jan00_daisy(unsigned int year)
{
/* daisy's base year is both 1 mod 4 and starts on a monday, so ... */
unsigned int by = TO_BASE(year);
#if defined WITH_FAST_ARITH
return by * 365U + by / 4U;
#else /* !WITH_FAST_ARITH */
by = by * 365U + by / 4U;
#if DT_DAISY_BASE_YEAR == 1917
if (UNLIKELY(year > 2100U)) {
by -= (year - 2001U) / 100U;
by += (year - 2001U) / 400U;
}
#elif DT_DAISY_BASE_YEAR == 1753
if (LIKELY(year > 1800U)) {
by -= (year - 1701U) / 100U;
by += (year - 1601U) / 400U;
}
#elif DT_DAISY_BASE_YEAR == 1601
by -= (year - 1601U) / 100U;
by += (year - 1601U) / 400U;
#endif
return by;
#endif /* WITH_FAST_ARITH */
}
#endif /* DAISY_ASPECT_HELPERS_ */
#if defined ASPECT_GETTERS && !defined DAISY_ASPECT_GETTERS_
#define DAISY_ASPECT_GETTERS_
static __attribute__((const)) dt_dow_t
__daisy_get_wday(dt_daisy_t d)
{
/* daisy wdays are simple because the base year is chosen so that day 0
* in the daisy calendar is a sunday */
return (dt_dow_t)((d % GREG_DAYS_P_WEEK) ?: DT_SUNDAY);
}
static __attribute__((const)) unsigned int
__daisy_get_year(dt_daisy_t d)
{
/* given days since 1917-01-01 (Mon), compute a year */
unsigned int by;
if (UNLIKELY(d == 0)) {
return 0U;
}
/* get an estimate for the year and readjust */
by = d / 365U;
if (UNLIKELY(TO_YEAR(by) > DT_MAX_YEAR)) {
return 0U;
} else if (UNLIKELY(__jan00_daisy(TO_YEAR(by)) >= d)) {
by--;
#if !defined WITH_FAST_ARITH
if (UNLIKELY(__jan00_daisy(TO_YEAR(by)) >= d)) {
by--;
}
#endif /* WITH_FAST_ARITH */
}
return TO_YEAR(by);
}
static __attribute__((const)) unsigned int
__daisy_get_yday(dt_daisy_t d)
{
dt_daisy_t j00;
unsigned int y;
if (UNLIKELY(d == 0)) {
return 0U;
}
y = __daisy_get_year(d);
j00 = __jan00_daisy(y);
return d - j00;
}
#endif /* DAISY_ASPECT_GETTERS_ */
#if defined ASPECT_CONV && !defined DAISY_ASPECT_CONV_
#define DAISY_ASPECT_CONV_
#if DT_DAISY_BASE_YEAR == 1917
# define DT_LDN_BASE (122068U/*lilian's 1917-01-00*/)
# define DT_JDN_BASE (2421228.5f/*julian's 1917-01-00*/)
# define DT_MDN_BASE (700170/*matlab's 1917-01-00*/)
#elif DT_DAISY_BASE_YEAR == 1753
# define DT_LDN_BASE (62169U/*lilian's 1753-01-00*/)
# define DT_JDN_BASE (2361329.5f/*julian's 1753-01-00*/)
# define DT_MDN_BASE (640271/*matlab's 1753-01-00*/)
#elif DT_DAISY_BASE_YEAR == 1601
# define DT_LDN_BASE (6652U/*lilian's 1601-01-00*/)
# define DT_JDN_BASE (2305812.5f/*julian's 1601-01-00*/)
# define DT_MDN_BASE (584754/*matlab's 1601-01-00*/)
#else
# error cannot convert to ldn, unknown base year
#endif
static __attribute__((const)) dt_ldn_t
__daisy_to_ldn(dt_daisy_t d)
{
return d + DT_LDN_BASE;
}
static __attribute__((const)) dt_jdn_t
__daisy_to_jdn(dt_daisy_t d)
{
return (dt_jdn_t)d + DT_JDN_BASE;
}
static __attribute__((const)) dt_mdn_t
__daisy_to_mdn(dt_daisy_t d)
{
return (dt_mdn_t)d + DT_MDN_BASE;
}
static __attribute__((const)) dt_daisy_t
__ldn_to_daisy(dt_ldn_t d)
{
dt_sdaisy_t tmp;
if ((tmp = d - DT_LDN_BASE) > 0) {
return (dt_daisy_t)tmp;
}
return 0U;
}
static __attribute__((const)) dt_daisy_t
__jdn_to_daisy(dt_jdn_t d)
{
float tmp;
if ((tmp = d - DT_JDN_BASE) > 0.0f) {
return (dt_daisy_t)tmp;
}
return 0U;
}
static __attribute__((const)) dt_daisy_t
__mdn_to_daisy(dt_mdn_t d)
{
dt_sdaisy_t tmp;
if ((tmp = d - DT_MDN_BASE) > 0) {
return (dt_daisy_t)tmp;
}
return 0U;
}
DEFUN __attribute__((const)) dt_ymd_t
__daisy_to_ymd(dt_daisy_t that)
{
#if 1
/* cassio neri eaf */
#define s (82U)
#define K (584693U + 146097U * s)
#define L (400U * s)
if (UNLIKELY(that == 0 || that > 910674U)) {
return (dt_ymd_t){.u = 0};
} else {
const unsigned int N = that + K;
/* century */
const unsigned int N_1 = 4U * N + 3U;
const unsigned int C = N_1 / 146097U;
const unsigned int N_C = N_1 % 146097U / 4U;
/* year */
const unsigned int N_2 = 4U * N_C + 3U;
const uint64_t P_2 = (uint64_t)2939745ULL * (uint64_t)N_2;
const unsigned int Z = (unsigned int)(P_2 / 4294967296ULL);
const unsigned int N_Y = (unsigned int)(P_2 % 4294967296ULL) / 2939745U / 4U;
const unsigned int Y = 100U * C + Z;
/* month and day */
const unsigned int N_3 = 2141U * N_Y + 197913U;
const unsigned int M = N_3 / 65536U;
const unsigned int D = N_3 % 65536U / 2141U;
/* year correction */
const unsigned int J = N_Y >= 306U;
#if defined HAVE_ANON_STRUCTS_INIT
return (dt_ymd_t){.y = Y - L + J, .m = J ? M - 12 : M, .d = D + 1};
#else /* !HAVE_ANON_STRUCTS_INIT */
{
dt_ymd_t res;
res.y = Y - L + J;
res.m = J ? M - 12 : M;
res.d = D + 1;
return res;
}
#endif /* HAVE_ANON_STRUCTS_INIT */
}
#undef s
#undef K
#undef L
#else
dt_daisy_t j00;
unsigned int doy;
unsigned int y;
struct __md_s md;
if (UNLIKELY(that == 0)) {
return (dt_ymd_t){.u = 0};
} else if (UNLIKELY(!(y = __daisy_get_year(that)))) {
return (dt_ymd_t){.u = 0};
}
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 */
#endif
}
static __attribute__((const)) 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 __attribute__((const)) dt_ywd_t
__daisy_to_ywd(dt_daisy_t that)
{
const unsigned int wd = (that + GREG_DAYS_P_WEEK - 1) % GREG_DAYS_P_WEEK;
dt_dow_t dow = (dt_dow_t)(wd + 1U);
unsigned int y = __daisy_get_year(that);
int yd = that - __jan00_daisy(y);
return __make_ywd_yd_dow(y, yd, dow);
}
static __attribute__((const)) dt_yd_t
__daisy_to_yd(dt_daisy_t d)
{
int yd = __daisy_get_yday(d);
unsigned int y = __daisy_get_year(d);
#if defined HAVE_ANON_STRUCTS_INIT
return (dt_yd_t){.y = y, .d = yd};
#else
dt_yd_t res;
res.y = y;
res.d = yd;
return res;
#endif
}
#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 __attribute__((const)) dt_daisy_t
__daisy_add_d(dt_daisy_t d, int n)
{
/* add N days to D */
d += n;
return d;
}
static __attribute__((const)) 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;
}
static __attribute__((const)) dt_daisy_t
__daisy_add_w(dt_daisy_t d, int n)
{
/* add N weeks to D */
return __daisy_add_d(d, GREG_DAYS_P_WEEK * n);
}
#endif /* ASPECT_ADD */
#if defined ASPECT_DIFF && !defined DAISY_ASPECT_DIFF_
#define DAISY_ASPECT_DIFF_
static __attribute__((const)) struct dt_ddur_s
__daisy_diff(dt_daisy_t d1, dt_daisy_t d2)
{
/* compute d2 - d1 */
int32_t diff = d2 - d1;
return dt_make_ddur(DT_DURD, diff);
}
#endif /* ASPECT_DIFF */
#if defined ASPECT_STRF && !defined DAISY_ASPECT_STRF_
#define DAISY_ASPECT_STRF_
DEFUN void
__prep_strfd_daisy(struct strpd_s *tgt, dt_daisy_t d)
{
dt_ymd_t tmp = __daisy_to_ymd(d);
tgt->y = tmp.y;
tgt->m = tmp.m;
tgt->d = tmp.d;
return;
}
#endif /* ASPECT_STRF */
/* daisy.c ends here */
|