Ruby  2.5.0dev(2017-10-22revision60238)
time.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  time.c -
4 
5  $Author$
6  created at: Tue Dec 28 14:31:59 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 #define _DEFAULT_SOURCE
13 #define _BSD_SOURCE
14 #include "internal.h"
15 #include <sys/types.h>
16 #include <time.h>
17 #include <errno.h>
18 
19 #ifdef HAVE_UNISTD_H
20 #include <unistd.h>
21 #endif
22 
23 #include <float.h>
24 #include <math.h>
25 
26 #ifdef HAVE_STRINGS_H
27 #include <strings.h>
28 #endif
29 
30 #if defined(HAVE_SYS_TIME_H)
31 #include <sys/time.h>
32 #endif
33 
34 #include "timev.h"
35 #include "id.h"
36 
37 static ID id_divmod, id_submicro, id_nano_num, id_nano_den, id_offset, id_zone;
38 static ID id_quo, id_div;
39 static ID id_nanosecond, id_microsecond, id_millisecond, id_nsec, id_usec;
40 
41 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
42 #define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
43 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
44 #define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
45 #define VTM_WDAY_INITVAL (7)
46 #define VTM_ISDST_INITVAL (3)
47 #define TO_GMT_INITVAL (3)
48 
49 static int
50 eq(VALUE x, VALUE y)
51 {
52  if (FIXNUM_P(x) && FIXNUM_P(y)) {
53  return x == y;
54  }
55  return RTEST(rb_funcall(x, idEq, 1, y));
56 }
57 
58 static int
59 cmp(VALUE x, VALUE y)
60 {
61  if (FIXNUM_P(x) && FIXNUM_P(y)) {
62  if ((long)x < (long)y)
63  return -1;
64  if ((long)x > (long)y)
65  return 1;
66  return 0;
67  }
68  if (RB_TYPE_P(x, T_BIGNUM)) return FIX2INT(rb_big_cmp(x, y));
69  return rb_cmpint(rb_funcall(x, idCmp, 1, y), x, y);
70 }
71 
72 #define ne(x,y) (!eq((x),(y)))
73 #define lt(x,y) (cmp((x),(y)) < 0)
74 #define gt(x,y) (cmp((x),(y)) > 0)
75 #define le(x,y) (cmp((x),(y)) <= 0)
76 #define ge(x,y) (cmp((x),(y)) >= 0)
77 
78 static VALUE
79 addv(VALUE x, VALUE y)
80 {
81  if (FIXNUM_P(x) && FIXNUM_P(y)) {
82  return LONG2NUM(FIX2LONG(x) + FIX2LONG(y));
83  }
84  if (RB_TYPE_P(x, T_BIGNUM)) return rb_big_plus(x, y);
85  return rb_funcall(x, '+', 1, y);
86 }
87 
88 static VALUE
89 subv(VALUE x, VALUE y)
90 {
91  if (FIXNUM_P(x) && FIXNUM_P(y)) {
92  return LONG2NUM(FIX2LONG(x) - FIX2LONG(y));
93  }
94  if (RB_TYPE_P(x, T_BIGNUM)) return rb_big_minus(x, y);
95  return rb_funcall(x, '-', 1, y);
96 }
97 
98 static VALUE
99 mulv(VALUE x, VALUE y)
100 {
101  if (FIXNUM_P(x) && FIXNUM_P(y)) {
102  return rb_fix_mul_fix(x, y);
103  }
104  if (RB_TYPE_P(x, T_BIGNUM))
105  return rb_big_mul(x, y);
106  return rb_funcall(x, '*', 1, y);
107 }
108 
109 static VALUE
110 divv(VALUE x, VALUE y)
111 {
112  if (FIXNUM_P(x) && FIXNUM_P(y)) {
113  return rb_fix_div_fix(x, y);
114  }
115  if (RB_TYPE_P(x, T_BIGNUM))
116  return rb_big_div(x, y);
117  return rb_funcall(x, id_div, 1, y);
118 }
119 
120 static VALUE
121 modv(VALUE x, VALUE y)
122 {
123  if (FIXNUM_P(y)) {
124  if (FIX2LONG(y) == 0) rb_num_zerodiv();
125  if (FIXNUM_P(x)) return rb_fix_mod_fix(x, y);
126  }
127  if (RB_TYPE_P(x, T_BIGNUM)) return rb_big_modulo(x, y);
128  return rb_funcall(x, '%', 1, y);
129 }
130 
131 #define neg(x) (subv(INT2FIX(0), (x)))
132 
133 static VALUE
134 quov(VALUE x, VALUE y)
135 {
136  VALUE ret;
137  if (FIXNUM_P(x) && FIXNUM_P(y)) {
138  long a, b, c;
139  a = FIX2LONG(x);
140  b = FIX2LONG(y);
141  if (b == 0) rb_num_zerodiv();
142  if (a == FIXNUM_MIN && b == -1) return LONG2NUM(-a);
143  c = a / b;
144  if (c * b == a) {
145  return LONG2FIX(c);
146  }
147  }
148  ret = rb_numeric_quo(x, y);
149  if (RB_TYPE_P(ret, T_RATIONAL) &&
150  RRATIONAL(ret)->den == INT2FIX(1)) {
151  ret = RRATIONAL(ret)->num;
152  }
153  return ret;
154 }
155 
156 #define mulquov(x,y,z) (((y) == (z)) ? (x) : quov(mulv((x),(y)),(z)))
157 
158 static void
159 divmodv(VALUE n, VALUE d, VALUE *q, VALUE *r)
160 {
161  VALUE tmp, ary;
162  if (FIXNUM_P(d)) {
163  if (FIX2LONG(d) == 0) rb_num_zerodiv();
164  if (FIXNUM_P(n)) {
165  rb_fix_divmod_fix(n, d, q, r);
166  return;
167  }
168  }
169  tmp = rb_funcall(n, id_divmod, 1, d);
170  ary = rb_check_array_type(tmp);
171  if (NIL_P(ary)) {
172  rb_raise(rb_eTypeError, "unexpected divmod result: into %"PRIsVALUE,
173  rb_obj_class(tmp));
174  }
175  *q = rb_ary_entry(ary, 0);
176  *r = rb_ary_entry(ary, 1);
177 }
178 
179 #if SIZEOF_LONG == 8
180 # define INT64toNUM(x) LONG2NUM(x)
181 #elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
182 # define INT64toNUM(x) LL2NUM(x)
183 #endif
184 
185 #if defined(HAVE_UINT64_T) && SIZEOF_LONG*2 <= SIZEOF_UINT64_T
186  typedef uint64_t uwideint_t;
187  typedef int64_t wideint_t;
188  typedef uint64_t WIDEVALUE;
189  typedef int64_t SIGNED_WIDEVALUE;
190 # define WIDEVALUE_IS_WIDER 1
191 # define UWIDEINT_MAX UINT64_MAX
192 # define WIDEINT_MAX INT64_MAX
193 # define WIDEINT_MIN INT64_MIN
194 # define FIXWINT_P(tv) ((tv) & 1)
195 # define FIXWVtoINT64(tv) RSHIFT((SIGNED_WIDEVALUE)(tv), 1)
196 # define INT64toFIXWV(wi) ((WIDEVALUE)((SIGNED_WIDEVALUE)(wi) << 1 | FIXNUM_FLAG))
197 # define FIXWV_MAX (((int64_t)1 << 62) - 1)
198 # define FIXWV_MIN (-((int64_t)1 << 62))
199 # define FIXWVABLE(wi) (POSFIXWVABLE(wi) && NEGFIXWVABLE(wi))
200 # define WINT2FIXWV(i) WIDEVAL_WRAP(INT64toFIXWV(i))
201 # define FIXWV2WINT(w) FIXWVtoINT64(WIDEVAL_GET(w))
202 #else
203  typedef unsigned long uwideint_t;
204  typedef long wideint_t;
205  typedef VALUE WIDEVALUE;
207 # define WIDEVALUE_IS_WIDER 0
208 # define UWIDEINT_MAX ULONG_MAX
209 # define WIDEINT_MAX LONG_MAX
210 # define WIDEINT_MIN LONG_MIN
211 # define FIXWINT_P(v) FIXNUM_P(v)
212 # define FIXWV_MAX FIXNUM_MAX
213 # define FIXWV_MIN FIXNUM_MIN
214 # define FIXWVABLE(i) FIXABLE(i)
215 # define WINT2FIXWV(i) WIDEVAL_WRAP(LONG2FIX(i))
216 # define FIXWV2WINT(w) FIX2LONG(WIDEVAL_GET(w))
217 #endif
218 
219 #define POSFIXWVABLE(wi) ((wi) < FIXWV_MAX+1)
220 #define NEGFIXWVABLE(wi) ((wi) >= FIXWV_MIN)
221 #define FIXWV_P(w) FIXWINT_P(WIDEVAL_GET(w))
222 #define MUL_OVERFLOW_FIXWV_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXWV_MIN, FIXWV_MAX)
223 
224 /* #define STRUCT_WIDEVAL */
225 #ifdef STRUCT_WIDEVAL
226  /* for type checking */
227  typedef struct {
228  WIDEVALUE value;
229  } wideval_t;
230  static inline wideval_t WIDEVAL_WRAP(WIDEVALUE v) { wideval_t w = { v }; return w; }
231 # define WIDEVAL_GET(w) ((w).value)
232 #else
234 # define WIDEVAL_WRAP(v) (v)
235 # define WIDEVAL_GET(w) (w)
236 #endif
237 
238 #if WIDEVALUE_IS_WIDER
239  static inline wideval_t
240  wint2wv(wideint_t wi)
241  {
242  if (FIXWVABLE(wi))
243  return WINT2FIXWV(wi);
244  else
245  return WIDEVAL_WRAP(INT64toNUM(wi));
246  }
247 # define WINT2WV(wi) wint2wv(wi)
248 #else
249 # define WINT2WV(wi) WIDEVAL_WRAP(LONG2NUM(wi))
250 #endif
251 
252 static inline VALUE
253 w2v(wideval_t w)
254 {
255 #if WIDEVALUE_IS_WIDER
256  if (FIXWV_P(w))
257  return INT64toNUM(FIXWV2WINT(w));
258  return (VALUE)WIDEVAL_GET(w);
259 #else
260  return WIDEVAL_GET(w);
261 #endif
262 }
263 
264 #if WIDEVALUE_IS_WIDER
265 static wideval_t
266 v2w_bignum(VALUE v)
267 {
268  int sign;
269  uwideint_t u;
270  sign = rb_integer_pack(v, &u, 1, sizeof(u), 0,
272  if (sign == 0)
273  return WINT2FIXWV(0);
274  else if (sign == -1) {
275  if (u <= -FIXWV_MIN)
276  return WINT2FIXWV(-(wideint_t)u);
277  }
278  else if (sign == +1) {
279  if (u <= FIXWV_MAX)
280  return WINT2FIXWV((wideint_t)u);
281  }
282  return WIDEVAL_WRAP(v);
283 }
284 #endif
285 
286 static inline wideval_t
287 v2w(VALUE v)
288 {
289  if (RB_TYPE_P(v, T_RATIONAL)) {
290  if (RRATIONAL(v)->den != LONG2FIX(1))
291  return v;
292  v = RRATIONAL(v)->num;
293  }
294 #if WIDEVALUE_IS_WIDER
295  if (FIXNUM_P(v)) {
296  return WIDEVAL_WRAP((WIDEVALUE)(SIGNED_WIDEVALUE)(long)v);
297  }
298  else if (RB_TYPE_P(v, T_BIGNUM) &&
299  rb_absint_size(v, NULL) <= sizeof(WIDEVALUE)) {
300  return v2w_bignum(v);
301  }
302 #endif
303  return WIDEVAL_WRAP(v);
304 }
305 
306 static int
307 weq(wideval_t wx, wideval_t wy)
308 {
309 #if WIDEVALUE_IS_WIDER
310  if (FIXWV_P(wx) && FIXWV_P(wy)) {
311  return WIDEVAL_GET(wx) == WIDEVAL_GET(wy);
312  }
313  return RTEST(rb_funcall(w2v(wx), idEq, 1, w2v(wy)));
314 #else
315  return eq(WIDEVAL_GET(wx), WIDEVAL_GET(wy));
316 #endif
317 }
318 
319 static int
320 wcmp(wideval_t wx, wideval_t wy)
321 {
322  VALUE x, y;
323 #if WIDEVALUE_IS_WIDER
324  if (FIXWV_P(wx) && FIXWV_P(wy)) {
325  wideint_t a, b;
326  a = FIXWV2WINT(wx);
327  b = FIXWV2WINT(wy);
328  if (a < b)
329  return -1;
330  if (a > b)
331  return 1;
332  return 0;
333  }
334 #endif
335  x = w2v(wx);
336  y = w2v(wy);
337  return cmp(x, y);
338 }
339 
340 #define wne(x,y) (!weq((x),(y)))
341 #define wlt(x,y) (wcmp((x),(y)) < 0)
342 #define wgt(x,y) (wcmp((x),(y)) > 0)
343 #define wle(x,y) (wcmp((x),(y)) <= 0)
344 #define wge(x,y) (wcmp((x),(y)) >= 0)
345 
346 static wideval_t
347 wadd(wideval_t wx, wideval_t wy)
348 {
349 #if WIDEVALUE_IS_WIDER
350  if (FIXWV_P(wx) && FIXWV_P(wy)) {
351  wideint_t r = FIXWV2WINT(wx) + FIXWV2WINT(wy);
352  return WINT2WV(r);
353  }
354 #endif
355  return v2w(addv(w2v(wx), w2v(wy)));
356 }
357 
358 static wideval_t
359 wsub(wideval_t wx, wideval_t wy)
360 {
361 #if WIDEVALUE_IS_WIDER
362  if (FIXWV_P(wx) && FIXWV_P(wy)) {
363  wideint_t r = FIXWV2WINT(wx) - FIXWV2WINT(wy);
364  return WINT2WV(r);
365  }
366 #endif
367  return v2w(subv(w2v(wx), w2v(wy)));
368 }
369 
370 static wideval_t
371 wmul(wideval_t wx, wideval_t wy)
372 {
373 #if WIDEVALUE_IS_WIDER
374  if (FIXWV_P(wx) && FIXWV_P(wy)) {
376  return WINT2WV(FIXWV2WINT(wx) * FIXWV2WINT(wy));
377  }
378 #endif
379  return v2w(mulv(w2v(wx), w2v(wy)));
380 }
381 
382 static wideval_t
383 wquo(wideval_t wx, wideval_t wy)
384 {
385 #if WIDEVALUE_IS_WIDER
386  if (FIXWV_P(wx) && FIXWV_P(wy)) {
387  wideint_t a, b, c;
388  a = FIXWV2WINT(wx);
389  b = FIXWV2WINT(wy);
390  if (b == 0) rb_num_zerodiv();
391  c = a / b;
392  if (c * b == a) {
393  return WINT2WV(c);
394  }
395  }
396 #endif
397  return v2w(quov(w2v(wx), w2v(wy)));
398 }
399 
400 #define wmulquo(x,y,z) ((WIDEVAL_GET(y) == WIDEVAL_GET(z)) ? (x) : wquo(wmul((x),(y)),(z)))
401 #define wmulquoll(x,y,z) (((y) == (z)) ? (x) : wquo(wmul((x),WINT2WV(y)),WINT2WV(z)))
402 
403 #if WIDEVALUE_IS_WIDER
404 static int
405 wdivmod0(wideval_t wn, wideval_t wd, wideval_t *wq, wideval_t *wr)
406 {
407  if (FIXWV_P(wn) && FIXWV_P(wd)) {
408  wideint_t n, d, q, r;
409  d = FIXWV2WINT(wd);
410  if (d == 0) rb_num_zerodiv();
411  if (d == 1) {
412  *wq = wn;
413  *wr = WINT2FIXWV(0);
414  return 1;
415  }
416  if (d == -1) {
417  wideint_t xneg = -FIXWV2WINT(wn);
418  *wq = WINT2WV(xneg);
419  *wr = WINT2FIXWV(0);
420  return 1;
421  }
422  n = FIXWV2WINT(wn);
423  if (n == 0) {
424  *wq = WINT2FIXWV(0);
425  *wr = WINT2FIXWV(0);
426  return 1;
427  }
428  q = n / d;
429  r = n % d;
430  if (d > 0 ? r < 0 : r > 0) {
431  q -= 1;
432  r += d;
433  }
434  *wq = WINT2FIXWV(q);
435  *wr = WINT2FIXWV(r);
436  return 1;
437  }
438  return 0;
439 }
440 #endif
441 
442 static void
443 wdivmod(wideval_t wn, wideval_t wd, wideval_t *wq, wideval_t *wr)
444 {
445  VALUE vq, vr;
446 #if WIDEVALUE_IS_WIDER
447  if (wdivmod0(wn, wd, wq, wr)) return;
448 #endif
449  divmodv(w2v(wn), w2v(wd), &vq, &vr);
450  *wq = v2w(vq);
451  *wr = v2w(vr);
452 }
453 
454 static void
455 wmuldivmod(wideval_t wx, wideval_t wy, wideval_t wz, wideval_t *wq, wideval_t *wr)
456 {
457  if (WIDEVAL_GET(wy) == WIDEVAL_GET(wz)) {
458  *wq = wx;
459  *wr = WINT2FIXWV(0);
460  return;
461  }
462  wdivmod(wmul(wx,wy), wz, wq, wr);
463 }
464 
465 static wideval_t
466 wdiv(wideval_t wx, wideval_t wy)
467 {
468 #if WIDEVALUE_IS_WIDER
469  wideval_t q, dmy;
470  if (wdivmod0(wx, wy, &q, &dmy)) return q;
471 #endif
472  return v2w(divv(w2v(wx), w2v(wy)));
473 }
474 
475 static wideval_t
476 wmod(wideval_t wx, wideval_t wy)
477 {
478 #if WIDEVALUE_IS_WIDER
479  wideval_t r, dmy;
480  if (wdivmod0(wx, wy, &dmy, &r)) return r;
481 #endif
482  return v2w(modv(w2v(wx), w2v(wy)));
483 }
484 
485 static VALUE
486 num_exact(VALUE v)
487 {
488  VALUE tmp;
489 
490  if (NIL_P(v)) {
491  rb_raise(rb_eTypeError, "can't convert nil into an exact number");
492  }
493  else if (RB_INTEGER_TYPE_P(v)) {
494  return v;
495  }
496  else if (RB_TYPE_P(v, T_RATIONAL)) {
497  goto rational;
498  }
499  else if (RB_TYPE_P(v, T_STRING)) {
500  goto typeerror;
501  }
502  else {
503  if ((tmp = rb_check_funcall(v, rb_intern("to_r"), 0, NULL)) != Qundef) {
504  /* test to_int method availability to reject non-Numeric
505  * objects such as String, Time, etc which have to_r method. */
506  if (!rb_respond_to(v, rb_intern("to_int"))) goto typeerror;
507  }
508  else if (!NIL_P(tmp = rb_check_to_int(v))) {
509  return tmp;
510  }
511  else {
512  goto typeerror;
513  }
514  }
515 
516  if (RB_INTEGER_TYPE_P(tmp)) {
517  v = tmp;
518  }
519  else if (RB_TYPE_P(tmp, T_RATIONAL)) {
520  v = tmp;
521  rational:
522  if (RRATIONAL(v)->den == INT2FIX(1))
523  v = RRATIONAL(v)->num;
524  }
525  else {
526  typeerror:
527  rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into an exact number",
528  rb_obj_class(v));
529  }
530  return v;
531 }
532 
533 /* time_t */
534 
535 static wideval_t
536 rb_time_magnify(wideval_t w)
537 {
538  return wmul(w, WINT2FIXWV(TIME_SCALE));
539 }
540 
541 static wideval_t
542 rb_time_unmagnify(wideval_t w)
543 {
544  return wquo(w, WINT2FIXWV(TIME_SCALE));
545 }
546 
547 static VALUE
548 rb_time_unmagnify_to_float(wideval_t w)
549 {
550  VALUE v;
551 #if WIDEVALUE_IS_WIDER
552  if (FIXWV_P(w)) {
553  wideint_t a, b, c;
554  a = FIXWV2WINT(w);
555  b = TIME_SCALE;
556  c = a / b;
557  if (c * b == a) {
558  return DBL2NUM((double)c);
559  }
560  v = DBL2NUM((double)FIXWV2WINT(w));
561  return quov(v, DBL2NUM(TIME_SCALE));
562  }
563 #endif
564  v = w2v(w);
565  if (RB_TYPE_P(v, T_RATIONAL))
566  return rb_Float(quov(v, INT2FIX(TIME_SCALE)));
567  else
568  return quov(v, DBL2NUM(TIME_SCALE));
569 }
570 
571 static void
572 split_second(wideval_t timew, wideval_t *timew_p, VALUE *subsecx_p)
573 {
574  wideval_t q, r;
575  wdivmod(timew, WINT2FIXWV(TIME_SCALE), &q, &r);
576  *timew_p = q;
577  *subsecx_p = w2v(r);
578 }
579 
580 static wideval_t
581 timet2wv(time_t t)
582 {
583 #if WIDEVALUE_IS_WIDER
584  if (TIMET_MIN == 0) {
585  uwideint_t wi = (uwideint_t)t;
586  if (wi <= FIXWV_MAX) {
587  return WINT2FIXWV(wi);
588  }
589  }
590  else {
591  wideint_t wi = (wideint_t)t;
592  if (FIXWV_MIN <= wi && wi <= FIXWV_MAX) {
593  return WINT2FIXWV(wi);
594  }
595  }
596 #endif
597  return v2w(TIMET2NUM(t));
598 }
599 #define TIMET2WV(t) timet2wv(t)
600 
601 static time_t
602 wv2timet(wideval_t w)
603 {
604 #if WIDEVALUE_IS_WIDER
605  if (FIXWV_P(w)) {
606  wideint_t wi = FIXWV2WINT(w);
607  if (TIMET_MIN == 0) {
608  if (wi < 0)
609  rb_raise(rb_eRangeError, "negative value to convert into `time_t'");
610  if (TIMET_MAX < (uwideint_t)wi)
611  rb_raise(rb_eRangeError, "too big to convert into `time_t'");
612  }
613  else {
614  if (wi < TIMET_MIN || TIMET_MAX < wi)
615  rb_raise(rb_eRangeError, "too big to convert into `time_t'");
616  }
617  return (time_t)wi;
618  }
619 #endif
620  return NUM2TIMET(w2v(w));
621 }
622 #define WV2TIMET(t) wv2timet(t)
623 
625 static VALUE time_utc_offset _((VALUE));
626 
627 static int obj2int(VALUE obj);
628 static uint32_t obj2ubits(VALUE obj, size_t bits);
629 static VALUE obj2vint(VALUE obj);
630 static uint32_t month_arg(VALUE arg);
631 static VALUE validate_utc_offset(VALUE utc_offset);
632 static VALUE validate_zone_name(VALUE zone_name);
633 static void validate_vtm(struct vtm *vtm);
634 static uint32_t obj2subsecx(VALUE obj, VALUE *subsecx);
635 
636 static VALUE time_gmtime(VALUE);
637 static VALUE time_localtime(VALUE);
638 static VALUE time_fixoff(VALUE);
639 
640 static time_t timegm_noleapsecond(struct tm *tm);
641 static int tmcmp(struct tm *a, struct tm *b);
642 static int vtmcmp(struct vtm *a, struct vtm *b);
643 static const char *find_time_t(struct tm *tptr, int utc_p, time_t *tp);
644 
645 static struct vtm *localtimew(wideval_t timew, struct vtm *result);
646 
647 static int leap_year_p(long y);
648 #define leap_year_v_p(y) leap_year_p(NUM2LONG(modv((y), INT2FIX(400))))
649 
650 static struct tm *
651 rb_localtime_r(const time_t *t, struct tm *result)
652 {
653 #if defined __APPLE__ && defined __LP64__
654  if (*t != (time_t)(int)*t) return NULL;
655 #endif
656 #ifdef HAVE_GMTIME_R
657  result = localtime_r(t, result);
658 #else
659  {
660  struct tm *tmp = localtime(t);
661  if (tmp) *result = *tmp;
662  }
663 #endif
664 #if defined(HAVE_MKTIME) && defined(LOCALTIME_OVERFLOW_PROBLEM)
665  if (result) {
666  long gmtoff1 = 0;
667  long gmtoff2 = 0;
668  struct tm tmp = *result;
669  time_t t2;
670  t2 = mktime(&tmp);
671 # if defined(HAVE_STRUCT_TM_TM_GMTOFF)
672  gmtoff1 = result->tm_gmtoff;
673  gmtoff2 = tmp.tm_gmtoff;
674 # endif
675  if (*t + gmtoff1 != t2 + gmtoff2)
676  result = NULL;
677  }
678 #endif
679  return result;
680 }
681 #define LOCALTIME(tm, result) (tzset(),rb_localtime_r((tm), &(result)))
682 
683 #ifndef HAVE_STRUCT_TM_TM_GMTOFF
684 static struct tm *
685 rb_gmtime_r(const time_t *t, struct tm *result)
686 {
687 #ifdef HAVE_GMTIME_R
688  result = gmtime_r(t, result);
689 #else
690  struct tm *tmp = gmtime(t);
691  if (tmp) *result = *tmp;
692 #endif
693 #if defined(HAVE_TIMEGM) && defined(LOCALTIME_OVERFLOW_PROBLEM)
694  if (result && *t != timegm(result)) {
695  return NULL;
696  }
697 #endif
698  return result;
699 }
700 # define GMTIME(tm, result) rb_gmtime_r((tm), &(result))
701 #endif
702 
703 static const int common_year_yday_offset[] = {
704  -1,
705  -1 + 31,
706  -1 + 31 + 28,
707  -1 + 31 + 28 + 31,
708  -1 + 31 + 28 + 31 + 30,
709  -1 + 31 + 28 + 31 + 30 + 31,
710  -1 + 31 + 28 + 31 + 30 + 31 + 30,
711  -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31,
712  -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
713  -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
714  -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
715  -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
716  /* 1 2 3 4 5 6 7 8 9 10 11 */
717 };
718 static const int leap_year_yday_offset[] = {
719  -1,
720  -1 + 31,
721  -1 + 31 + 29,
722  -1 + 31 + 29 + 31,
723  -1 + 31 + 29 + 31 + 30,
724  -1 + 31 + 29 + 31 + 30 + 31,
725  -1 + 31 + 29 + 31 + 30 + 31 + 30,
726  -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31,
727  -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
728  -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
729  -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
730  -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
731  /* 1 2 3 4 5 6 7 8 9 10 11 */
732 };
733 
734 static const int common_year_days_in_month[] = {
735  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
736 };
737 static const int leap_year_days_in_month[] = {
738  31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
739 };
740 
741 static int
742 calc_tm_yday(long tm_year, int tm_mon, int tm_mday)
743 {
744  int tm_year_mod400 = (int)MOD(tm_year, 400);
745  int tm_yday = tm_mday;
746 
747  if (leap_year_p(tm_year_mod400 + 1900))
748  tm_yday += leap_year_yday_offset[tm_mon];
749  else
750  tm_yday += common_year_yday_offset[tm_mon];
751 
752  return tm_yday;
753 }
754 
755 static wideval_t
756 timegmw_noleapsecond(struct vtm *vtm)
757 {
758  VALUE year1900;
759  VALUE q400, r400;
760  int year_mod400;
761  int yday;
762  long days_in400;
763  VALUE vdays, ret;
764  wideval_t wret;
765 
766  year1900 = subv(vtm->year, INT2FIX(1900));
767 
768  divmodv(year1900, INT2FIX(400), &q400, &r400);
769  year_mod400 = NUM2INT(r400);
770 
771  yday = calc_tm_yday(year_mod400, vtm->mon-1, vtm->mday);
772 
773  /*
774  * `Seconds Since the Epoch' in SUSv3:
775  * tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
776  * (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
777  * ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
778  */
779  ret = LONG2NUM(vtm->sec
780  + vtm->min*60
781  + vtm->hour*3600);
782  days_in400 = yday
783  - 70*365
784  + DIV(year_mod400 - 69, 4)
785  - DIV(year_mod400 - 1, 100)
786  + (year_mod400 + 299) / 400;
787  vdays = LONG2NUM(days_in400);
788  vdays = addv(vdays, mulv(q400, INT2FIX(97)));
789  vdays = addv(vdays, mulv(year1900, INT2FIX(365)));
790  wret = wadd(rb_time_magnify(v2w(ret)), wmul(rb_time_magnify(v2w(vdays)), WINT2FIXWV(86400)));
791  wret = wadd(wret, v2w(vtm->subsecx));
792 
793  return wret;
794 }
795 
796 static st_table *zone_table;
797 
798 static int
799 zone_str_update(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
800 {
801  const char *s = (const char *)*key;
802  const char **ret = (const char **)arg;
803 
804  if (existing) {
805  *ret = (const char *)*value;
806  return ST_STOP;
807  }
808  *ret = s = strdup(s);
809  *key = *value = (st_data_t)s;
810  return ST_CONTINUE;
811 }
812 
813 static const char *
814 zone_str(const char *s)
815 {
816  if (!zone_table)
817  zone_table = st_init_strtable();
818 
819  st_update(zone_table, (st_data_t)s, zone_str_update, (st_data_t)&s);
820  return s;
821 }
822 
823 static void
824 gmtimew_noleapsecond(wideval_t timew, struct vtm *vtm)
825 {
826  VALUE v;
827  int i, n, x, y;
828  const int *yday_offset;
829  int wday;
830  VALUE timev;
831  wideval_t timew2, w, w2;
832  VALUE subsecx;
833 
834  vtm->isdst = 0;
835 
836  split_second(timew, &timew2, &subsecx);
837  vtm->subsecx = subsecx;
838 
839  wdivmod(timew2, WINT2FIXWV(86400), &w2, &w);
840  timev = w2v(w2);
841  v = w2v(w);
842 
843  wday = NUM2INT(modv(timev, INT2FIX(7)));
844  vtm->wday = (wday + 4) % 7;
845 
846  n = NUM2INT(v);
847  vtm->sec = n % 60; n = n / 60;
848  vtm->min = n % 60; n = n / 60;
849  vtm->hour = n;
850 
851  /* 97 leap days in the 400 year cycle */
852  divmodv(timev, INT2FIX(400*365 + 97), &timev, &v);
853  vtm->year = mulv(timev, INT2FIX(400));
854 
855  /* n is the days in the 400 year cycle.
856  * the start of the cycle is 1970-01-01. */
857 
858  n = NUM2INT(v);
859  y = 1970;
860 
861  /* 30 years including 7 leap days (1972, 1976, ... 1996),
862  * 31 days in January 2000 and
863  * 29 days in February 2000
864  * from 1970-01-01 to 2000-02-29 */
865  if (30*365+7+31+29-1 <= n) {
866  /* 2000-02-29 or after */
867  if (n < 31*365+8) {
868  /* 2000-02-29 to 2000-12-31 */
869  y += 30;
870  n -= 30*365+7;
871  goto found;
872  }
873  else {
874  /* 2001-01-01 or after */
875  n -= 1;
876  }
877  }
878 
879  x = n / (365*100 + 24);
880  n = n % (365*100 + 24);
881  y += x * 100;
882  if (30*365+7+31+29-1 <= n) {
883  if (n < 31*365+7) {
884  y += 30;
885  n -= 30*365+7;
886  goto found;
887  }
888  else
889  n += 1;
890  }
891 
892  x = n / (365*4 + 1);
893  n = n % (365*4 + 1);
894  y += x * 4;
895  if (365*2+31+29-1 <= n) {
896  if (n < 365*2+366) {
897  y += 2;
898  n -= 365*2;
899  goto found;
900  }
901  else
902  n -= 1;
903  }
904 
905  x = n / 365;
906  n = n % 365;
907  y += x;
908 
909  found:
910  vtm->yday = n+1;
911  vtm->year = addv(vtm->year, INT2NUM(y));
912 
913  if (leap_year_p(y))
914  yday_offset = leap_year_yday_offset;
915  else
916  yday_offset = common_year_yday_offset;
917 
918  for (i = 0; i < 12; i++) {
919  if (yday_offset[i] < n) {
920  vtm->mon = i+1;
921  vtm->mday = n - yday_offset[i];
922  }
923  else
924  break;
925  }
926 
927  vtm->utc_offset = INT2FIX(0);
928  vtm->zone = "UTC";
929 }
930 
931 static struct tm *
932 gmtime_with_leapsecond(const time_t *timep, struct tm *result)
933 {
934 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
935  /* 4.4BSD counts leap seconds only with localtime, not with gmtime. */
936  struct tm *t;
937  int sign;
938  int gmtoff_sec, gmtoff_min, gmtoff_hour, gmtoff_day;
939  long gmtoff;
940  t = LOCALTIME(timep, *result);
941  if (t == NULL)
942  return NULL;
943 
944  /* subtract gmtoff */
945  if (t->tm_gmtoff < 0) {
946  sign = 1;
947  gmtoff = -t->tm_gmtoff;
948  }
949  else {
950  sign = -1;
951  gmtoff = t->tm_gmtoff;
952  }
953  gmtoff_sec = (int)(gmtoff % 60);
954  gmtoff = gmtoff / 60;
955  gmtoff_min = (int)(gmtoff % 60);
956  gmtoff = gmtoff / 60;
957  gmtoff_hour = (int)gmtoff; /* <= 12 */
958 
959  gmtoff_sec *= sign;
960  gmtoff_min *= sign;
961  gmtoff_hour *= sign;
962 
963  gmtoff_day = 0;
964 
965  if (gmtoff_sec) {
966  /* If gmtoff_sec == 0, don't change result->tm_sec.
967  * It may be 60 which is a leap second. */
968  result->tm_sec += gmtoff_sec;
969  if (result->tm_sec < 0) {
970  result->tm_sec += 60;
971  gmtoff_min -= 1;
972  }
973  if (60 <= result->tm_sec) {
974  result->tm_sec -= 60;
975  gmtoff_min += 1;
976  }
977  }
978  if (gmtoff_min) {
979  result->tm_min += gmtoff_min;
980  if (result->tm_min < 0) {
981  result->tm_min += 60;
982  gmtoff_hour -= 1;
983  }
984  if (60 <= result->tm_min) {
985  result->tm_min -= 60;
986  gmtoff_hour += 1;
987  }
988  }
989  if (gmtoff_hour) {
990  result->tm_hour += gmtoff_hour;
991  if (result->tm_hour < 0) {
992  result->tm_hour += 24;
993  gmtoff_day = -1;
994  }
995  if (24 <= result->tm_hour) {
996  result->tm_hour -= 24;
997  gmtoff_day = 1;
998  }
999  }
1000 
1001  if (gmtoff_day) {
1002  if (gmtoff_day < 0) {
1003  if (result->tm_yday == 0) {
1004  result->tm_mday = 31;
1005  result->tm_mon = 11; /* December */
1006  result->tm_year--;
1007  result->tm_yday = leap_year_p(result->tm_year + 1900) ? 365 : 364;
1008  }
1009  else if (result->tm_mday == 1) {
1010  const int *days_in_month = leap_year_p(result->tm_year + 1900) ?
1011  leap_year_days_in_month :
1012  common_year_days_in_month;
1013  result->tm_mon--;
1014  result->tm_mday = days_in_month[result->tm_mon];
1015  result->tm_yday--;
1016  }
1017  else {
1018  result->tm_mday--;
1019  result->tm_yday--;
1020  }
1021  result->tm_wday = (result->tm_wday + 6) % 7;
1022  }
1023  else {
1024  int leap = leap_year_p(result->tm_year + 1900);
1025  if (result->tm_yday == (leap ? 365 : 364)) {
1026  result->tm_year++;
1027  result->tm_mon = 0; /* January */
1028  result->tm_mday = 1;
1029  result->tm_yday = 0;
1030  }
1031  else if (result->tm_mday == (leap ? leap_year_days_in_month :
1032  common_year_days_in_month)[result->tm_mon]) {
1033  result->tm_mon++;
1034  result->tm_mday = 1;
1035  result->tm_yday++;
1036  }
1037  else {
1038  result->tm_mday++;
1039  result->tm_yday++;
1040  }
1041  result->tm_wday = (result->tm_wday + 1) % 7;
1042  }
1043  }
1044  result->tm_isdst = 0;
1045  result->tm_gmtoff = 0;
1046 #if defined(HAVE_TM_ZONE)
1047  result->tm_zone = (char *)"UTC";
1048 #endif
1049  return result;
1050 #else
1051  return GMTIME(timep, *result);
1052 #endif
1053 }
1054 
1055 static long this_year = 0;
1056 static time_t known_leap_seconds_limit;
1057 static int number_of_leap_seconds_known;
1058 
1059 static void
1060 init_leap_second_info(void)
1061 {
1062  /*
1063  * leap seconds are determined by IERS.
1064  * It is announced 6 months before the leap second.
1065  * So no one knows leap seconds in the future after the next year.
1066  */
1067  if (this_year == 0) {
1068  time_t now;
1069  struct tm *tm, result;
1070  struct vtm vtm;
1071  wideval_t timew;
1072  now = time(NULL);
1073  gmtime(&now);
1074  tm = gmtime_with_leapsecond(&now, &result);
1075  if (!tm) return;
1076  this_year = tm->tm_year;
1077 
1078  if (TIMET_MAX - now < (time_t)(366*86400))
1079  known_leap_seconds_limit = TIMET_MAX;
1080  else
1081  known_leap_seconds_limit = now + (time_t)(366*86400);
1082 
1083  if (!gmtime_with_leapsecond(&known_leap_seconds_limit, &result))
1084  return;
1085 
1086  vtm.year = LONG2NUM(result.tm_year + 1900);
1087  vtm.mon = result.tm_mon + 1;
1088  vtm.mday = result.tm_mday;
1089  vtm.hour = result.tm_hour;
1090  vtm.min = result.tm_min;
1091  vtm.sec = result.tm_sec;
1092  vtm.subsecx = INT2FIX(0);
1093  vtm.utc_offset = INT2FIX(0);
1094 
1095  timew = timegmw_noleapsecond(&vtm);
1096 
1097  number_of_leap_seconds_known = NUM2INT(w2v(wsub(TIMET2WV(known_leap_seconds_limit), rb_time_unmagnify(timew))));
1098  }
1099 }
1100 
1101 static wideval_t
1102 timegmw(struct vtm *vtm)
1103 {
1104  wideval_t timew;
1105  struct tm tm;
1106  time_t t;
1107  const char *errmsg;
1108 
1109  /* The first leap second is 1972-06-30 23:59:60 UTC.
1110  * No leap seconds before. */
1111  if (gt(INT2FIX(1972), vtm->year))
1112  return timegmw_noleapsecond(vtm);
1113 
1114  init_leap_second_info();
1115 
1116  timew = timegmw_noleapsecond(vtm);
1117 
1118  if (wlt(rb_time_magnify(TIMET2WV(known_leap_seconds_limit)), timew)) {
1119  return wadd(timew, rb_time_magnify(WINT2WV(number_of_leap_seconds_known)));
1120  }
1121 
1122  tm.tm_year = rb_long2int(NUM2LONG(vtm->year) - 1900);
1123  tm.tm_mon = vtm->mon - 1;
1124  tm.tm_mday = vtm->mday;
1125  tm.tm_hour = vtm->hour;
1126  tm.tm_min = vtm->min;
1127  tm.tm_sec = vtm->sec;
1128  tm.tm_isdst = 0;
1129 
1130  errmsg = find_time_t(&tm, 1, &t);
1131  if (errmsg)
1132  rb_raise(rb_eArgError, "%s", errmsg);
1133  return wadd(rb_time_magnify(TIMET2WV(t)), v2w(vtm->subsecx));
1134 }
1135 
1136 static struct vtm *
1137 gmtimew(wideval_t timew, struct vtm *result)
1138 {
1139  time_t t;
1140  struct tm tm;
1141  VALUE subsecx;
1142  wideval_t timew2;
1143 
1144  if (wlt(timew, WINT2FIXWV(0))) {
1145  gmtimew_noleapsecond(timew, result);
1146  return result;
1147  }
1148 
1149  init_leap_second_info();
1150 
1151  if (wlt(rb_time_magnify(TIMET2WV(known_leap_seconds_limit)), timew)) {
1152  timew = wsub(timew, rb_time_magnify(WINT2WV(number_of_leap_seconds_known)));
1153  gmtimew_noleapsecond(timew, result);
1154  return result;
1155  }
1156 
1157  split_second(timew, &timew2, &subsecx);
1158 
1159  t = WV2TIMET(timew2);
1160  if (!gmtime_with_leapsecond(&t, &tm))
1161  return NULL;
1162 
1163  result->year = LONG2NUM((long)tm.tm_year + 1900);
1164  result->mon = tm.tm_mon + 1;
1165  result->mday = tm.tm_mday;
1166  result->hour = tm.tm_hour;
1167  result->min = tm.tm_min;
1168  result->sec = tm.tm_sec;
1169  result->subsecx = subsecx;
1170  result->utc_offset = INT2FIX(0);
1171  result->wday = tm.tm_wday;
1172  result->yday = tm.tm_yday+1;
1173  result->isdst = tm.tm_isdst;
1174  result->zone = "UTC";
1175 
1176  return result;
1177 }
1178 
1179 static struct tm *localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, const char **zone);
1180 
1181 /*
1182  * The idea is borrowed from Perl:
1183  * http://web.archive.org/web/20080211114141/http://use.perl.org/articles/08/02/07/197204.shtml
1184  *
1185  * compat_common_month_table is generated by the following program.
1186  * This table finds the last month which starts at the same day of a week.
1187  * The year 2037 is not used because:
1188  * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=522949
1189  *
1190  * #!/usr/bin/ruby
1191  *
1192  * require 'date'
1193  *
1194  * h = {}
1195  * 2036.downto(2010) {|y|
1196  * 1.upto(12) {|m|
1197  * next if m == 2 && y % 4 == 0
1198  * d = Date.new(y,m,1)
1199  * h[m] ||= {}
1200  * h[m][d.wday] ||= y
1201  * }
1202  * }
1203  *
1204  * 1.upto(12) {|m|
1205  * print "{"
1206  * 0.upto(6) {|w|
1207  * y = h[m][w]
1208  * print " #{y},"
1209  * }
1210  * puts "},"
1211  * }
1212  *
1213  */
1214 static int compat_common_month_table[12][7] = {
1215  /* Sun Mon Tue Wed Thu Fri Sat */
1216  { 2034, 2035, 2036, 2031, 2032, 2027, 2033 }, /* January */
1217  { 2026, 2027, 2033, 2034, 2035, 2030, 2031 }, /* February */
1218  { 2026, 2032, 2033, 2034, 2035, 2030, 2036 }, /* March */
1219  { 2035, 2030, 2036, 2026, 2032, 2033, 2034 }, /* April */
1220  { 2033, 2034, 2035, 2030, 2036, 2026, 2032 }, /* May */
1221  { 2036, 2026, 2032, 2033, 2034, 2035, 2030 }, /* June */
1222  { 2035, 2030, 2036, 2026, 2032, 2033, 2034 }, /* July */
1223  { 2032, 2033, 2034, 2035, 2030, 2036, 2026 }, /* August */
1224  { 2030, 2036, 2026, 2032, 2033, 2034, 2035 }, /* September */
1225  { 2034, 2035, 2030, 2036, 2026, 2032, 2033 }, /* October */
1226  { 2026, 2032, 2033, 2034, 2035, 2030, 2036 }, /* November */
1227  { 2030, 2036, 2026, 2032, 2033, 2034, 2035 }, /* December */
1228 };
1229 
1230 /*
1231  * compat_leap_month_table is generated by following program.
1232  *
1233  * #!/usr/bin/ruby
1234  *
1235  * require 'date'
1236  *
1237  * h = {}
1238  * 2037.downto(2010) {|y|
1239  * 1.upto(12) {|m|
1240  * next unless m == 2 && y % 4 == 0
1241  * d = Date.new(y,m,1)
1242  * h[m] ||= {}
1243  * h[m][d.wday] ||= y
1244  * }
1245  * }
1246  *
1247  * 2.upto(2) {|m|
1248  * 0.upto(6) {|w|
1249  * y = h[m][w]
1250  * print " #{y},"
1251  * }
1252  * puts
1253  * }
1254  */
1255 static int compat_leap_month_table[7] = {
1256 /* Sun Mon Tue Wed Thu Fri Sat */
1257  2032, 2016, 2028, 2012, 2024, 2036, 2020, /* February */
1258 };
1259 
1260 static int
1261 calc_wday(int year, int month, int day)
1262 {
1263  int a, y, m;
1264  int wday;
1265 
1266  a = (14 - month) / 12;
1267  y = year + 4800 - a;
1268  m = month + 12 * a - 3;
1269  wday = day + (153*m+2)/5 + 365*y + y/4 - y/100 + y/400 + 2;
1270  wday = wday % 7;
1271  return wday;
1272 }
1273 
1274 static VALUE
1275 guess_local_offset(struct vtm *vtm_utc, int *isdst_ret, const char **zone_ret)
1276 {
1277  struct tm tm;
1278  long gmtoff;
1279  const char *zone;
1280  time_t t;
1281  struct vtm vtm2;
1282  VALUE timev;
1283  int y, wday;
1284 
1285  /* Daylight Saving Time was introduced in 1916.
1286  * So we don't need to care about DST before that. */
1287  if (lt(vtm_utc->year, INT2FIX(1916))) {
1288  VALUE off = INT2FIX(0);
1289  int isdst = 0;
1290  zone = "UTC";
1291 
1292 # if defined(NEGATIVE_TIME_T)
1293 # if SIZEOF_TIME_T <= 4
1294  /* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t. */
1295 # define THE_TIME_OLD_ENOUGH ((time_t)0x80000000)
1296 # else
1297  /* Since the Royal Greenwich Observatory was commissioned in 1675,
1298  no timezone defined using GMT at 1600. */
1299 # define THE_TIME_OLD_ENOUGH ((time_t)(1600-1970)*366*24*60*60)
1300 # endif
1301  if (localtime_with_gmtoff_zone((t = THE_TIME_OLD_ENOUGH, &t), &tm, &gmtoff, &zone)) {
1302  off = LONG2FIX(gmtoff);
1303  isdst = tm.tm_isdst;
1304  }
1305  else
1306 # endif
1307  /* 1970-01-01 00:00:00 UTC : The Unix epoch - the oldest time in portable time_t. */
1308  if (localtime_with_gmtoff_zone((t = 0, &t), &tm, &gmtoff, &zone)) {
1309  off = LONG2FIX(gmtoff);
1310  isdst = tm.tm_isdst;
1311  }
1312 
1313  if (isdst_ret)
1314  *isdst_ret = isdst;
1315  if (zone_ret)
1316  *zone_ret = zone;
1317  return off;
1318  }
1319 
1320  /* It is difficult to guess the future. */
1321 
1322  vtm2 = *vtm_utc;
1323 
1324  /* guess using a year before 2038. */
1325  y = NUM2INT(modv(vtm_utc->year, INT2FIX(400)));
1326  wday = calc_wday(y, vtm_utc->mon, 1);
1327  if (vtm_utc->mon == 2 && leap_year_p(y))
1328  vtm2.year = INT2FIX(compat_leap_month_table[wday]);
1329  else
1330  vtm2.year = INT2FIX(compat_common_month_table[vtm_utc->mon-1][wday]);
1331 
1332  timev = w2v(rb_time_unmagnify(timegmw(&vtm2)));
1333  t = NUM2TIMET(timev);
1334  zone = "UTC";
1335  if (localtime_with_gmtoff_zone(&t, &tm, &gmtoff, &zone)) {
1336  if (isdst_ret)
1337  *isdst_ret = tm.tm_isdst;
1338  if (zone_ret)
1339  *zone_ret = zone;
1340  return LONG2FIX(gmtoff);
1341  }
1342 
1343  {
1344  /* Use the current time offset as a last resort. */
1345  static time_t now = 0;
1346  static long now_gmtoff = 0;
1347  static const char *now_zone = "UTC";
1348  if (now == 0) {
1349  now = time(NULL);
1350  localtime_with_gmtoff_zone(&now, &tm, &now_gmtoff, &now_zone);
1351  }
1352  if (isdst_ret)
1353  *isdst_ret = tm.tm_isdst;
1354  if (zone_ret)
1355  *zone_ret = now_zone;
1356  return LONG2FIX(now_gmtoff);
1357  }
1358 }
1359 
1360 static VALUE
1361 small_vtm_sub(struct vtm *vtm1, struct vtm *vtm2)
1362 {
1363  int off;
1364 
1365  off = vtm1->sec - vtm2->sec;
1366  off += (vtm1->min - vtm2->min) * 60;
1367  off += (vtm1->hour - vtm2->hour) * 3600;
1368  if (ne(vtm1->year, vtm2->year))
1369  off += lt(vtm1->year, vtm2->year) ? -24*3600 : 24*3600;
1370  else if (vtm1->mon != vtm2->mon)
1371  off += vtm1->mon < vtm2->mon ? -24*3600 : 24*3600;
1372  else if (vtm1->mday != vtm2->mday)
1373  off += vtm1->mday < vtm2->mday ? -24*3600 : 24*3600;
1374 
1375  return INT2FIX(off);
1376 }
1377 
1378 static wideval_t
1379 timelocalw(struct vtm *vtm)
1380 {
1381  time_t t;
1382  struct tm tm;
1383  VALUE v;
1384  wideval_t timew1, timew2;
1385  struct vtm vtm1, vtm2;
1386  int n;
1387 
1388  if (FIXNUM_P(vtm->year)) {
1389  long l = FIX2LONG(vtm->year) - 1900;
1390  if (l < INT_MIN || INT_MAX < l)
1391  goto no_localtime;
1392  tm.tm_year = (int)l;
1393  }
1394  else {
1395  v = subv(vtm->year, INT2FIX(1900));
1396  if (lt(v, INT2NUM(INT_MIN)) || lt(INT2NUM(INT_MAX), v))
1397  goto no_localtime;
1398  tm.tm_year = NUM2INT(v);
1399  }
1400 
1401  tm.tm_mon = vtm->mon-1;
1402  tm.tm_mday = vtm->mday;
1403  tm.tm_hour = vtm->hour;
1404  tm.tm_min = vtm->min;
1405  tm.tm_sec = vtm->sec;
1406  tm.tm_isdst = vtm->isdst == VTM_ISDST_INITVAL ? -1 : vtm->isdst;
1407 
1408  if (find_time_t(&tm, 0, &t))
1409  goto no_localtime;
1410  return wadd(rb_time_magnify(TIMET2WV(t)), v2w(vtm->subsecx));
1411 
1412  no_localtime:
1413  timew1 = timegmw(vtm);
1414 
1415  if (!localtimew(timew1, &vtm1))
1416  rb_raise(rb_eArgError, "localtimew error");
1417 
1418  n = vtmcmp(vtm, &vtm1);
1419  if (n == 0) {
1420  timew1 = wsub(timew1, rb_time_magnify(WINT2FIXWV(12*3600)));
1421  if (!localtimew(timew1, &vtm1))
1422  rb_raise(rb_eArgError, "localtimew error");
1423  n = 1;
1424  }
1425 
1426  if (n < 0) {
1427  timew2 = timew1;
1428  vtm2 = vtm1;
1429  timew1 = wsub(timew1, rb_time_magnify(WINT2FIXWV(24*3600)));
1430  if (!localtimew(timew1, &vtm1))
1431  rb_raise(rb_eArgError, "localtimew error");
1432  }
1433  else {
1434  timew2 = wadd(timew1, rb_time_magnify(WINT2FIXWV(24*3600)));
1435  if (!localtimew(timew2, &vtm2))
1436  rb_raise(rb_eArgError, "localtimew error");
1437  }
1438  timew1 = wadd(timew1, rb_time_magnify(v2w(small_vtm_sub(vtm, &vtm1))));
1439  timew2 = wadd(timew2, rb_time_magnify(v2w(small_vtm_sub(vtm, &vtm2))));
1440 
1441  if (weq(timew1, timew2))
1442  return timew1;
1443 
1444  if (!localtimew(timew1, &vtm1))
1445  rb_raise(rb_eArgError, "localtimew error");
1446  if (vtm->hour != vtm1.hour || vtm->min != vtm1.min || vtm->sec != vtm1.sec)
1447  return timew2;
1448 
1449  if (!localtimew(timew2, &vtm2))
1450  rb_raise(rb_eArgError, "localtimew error");
1451  if (vtm->hour != vtm2.hour || vtm->min != vtm2.min || vtm->sec != vtm2.sec)
1452  return timew1;
1453 
1454  if (vtm->isdst)
1455  return lt(vtm1.utc_offset, vtm2.utc_offset) ? timew2 : timew1;
1456  else
1457  return lt(vtm1.utc_offset, vtm2.utc_offset) ? timew1 : timew2;
1458 }
1459 
1460 static struct tm *
1461 localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, const char **zone)
1462 {
1463  struct tm tm;
1464 
1465  if (LOCALTIME(t, tm)) {
1466 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
1467  *gmtoff = tm.tm_gmtoff;
1468 #else
1469  struct tm *u, *l;
1470  long off;
1471  struct tm tmbuf;
1472  l = &tm;
1473  u = GMTIME(t, tmbuf);
1474  if (!u)
1475  return NULL;
1476  if (l->tm_year != u->tm_year)
1477  off = l->tm_year < u->tm_year ? -1 : 1;
1478  else if (l->tm_mon != u->tm_mon)
1479  off = l->tm_mon < u->tm_mon ? -1 : 1;
1480  else if (l->tm_mday != u->tm_mday)
1481  off = l->tm_mday < u->tm_mday ? -1 : 1;
1482  else
1483  off = 0;
1484  off = off * 24 + l->tm_hour - u->tm_hour;
1485  off = off * 60 + l->tm_min - u->tm_min;
1486  off = off * 60 + l->tm_sec - u->tm_sec;
1487  *gmtoff = off;
1488 #endif
1489 
1490  if (zone) {
1491 #if defined(HAVE_TM_ZONE)
1492  if (tm.tm_zone)
1493  *zone = zone_str(tm.tm_zone);
1494  else
1495  *zone = zone_str("(NO-TIMEZONE-ABBREVIATION)");
1496 #elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT)
1497 # if RUBY_MSVCRT_VERSION >= 140
1498 # define tzname _tzname
1499 # define daylight _daylight
1500 # endif
1501  /* this needs tzset or localtime, instead of localtime_r */
1502  *zone = zone_str(tzname[daylight && tm.tm_isdst]);
1503 #else
1504  {
1505  char buf[64];
1506  strftime(buf, sizeof(buf), "%Z", &tm);
1507  *zone = zone_str(buf);
1508  }
1509 #endif
1510  }
1511 
1512  *result = tm;
1513  return result;
1514  }
1515  return NULL;
1516 }
1517 
1518 static int
1519 timew_out_of_timet_range(wideval_t timew)
1520 {
1521  VALUE timexv;
1522 #if WIDEVALUE_IS_WIDER && SIZEOF_TIME_T < SIZEOF_INT64_T
1523  if (FIXWV_P(timew)) {
1524  wideint_t t = FIXWV2WINT(timew);
1525  if (t < TIME_SCALE * (wideint_t)TIMET_MIN ||
1526  TIME_SCALE * (1 + (wideint_t)TIMET_MAX) <= t)
1527  return 1;
1528  return 0;
1529  }
1530 #endif
1531 #if SIZEOF_TIME_T == SIZEOF_INT64_T
1532  if (FIXWV_P(timew)) {
1533  wideint_t t = FIXWV2WINT(timew);
1534  if (~(time_t)0 <= 0) {
1535  return 0;
1536  }
1537  else {
1538  if (t < 0)
1539  return 1;
1540  return 0;
1541  }
1542  }
1543 #endif
1544  timexv = w2v(timew);
1545  if (lt(timexv, mulv(INT2FIX(TIME_SCALE), TIMET2NUM(TIMET_MIN))) ||
1546  le(mulv(INT2FIX(TIME_SCALE), addv(TIMET2NUM(TIMET_MAX), INT2FIX(1))), timexv))
1547  return 1;
1548  return 0;
1549 }
1550 
1551 static struct vtm *
1552 localtimew(wideval_t timew, struct vtm *result)
1553 {
1554  VALUE subsecx, offset;
1555  const char *zone;
1556  int isdst;
1557 
1558  if (!timew_out_of_timet_range(timew)) {
1559  time_t t;
1560  struct tm tm;
1561  long gmtoff;
1562  wideval_t timew2;
1563 
1564  split_second(timew, &timew2, &subsecx);
1565 
1566  t = WV2TIMET(timew2);
1567 
1568  if (localtime_with_gmtoff_zone(&t, &tm, &gmtoff, &zone)) {
1569  result->year = LONG2NUM((long)tm.tm_year + 1900);
1570  result->mon = tm.tm_mon + 1;
1571  result->mday = tm.tm_mday;
1572  result->hour = tm.tm_hour;
1573  result->min = tm.tm_min;
1574  result->sec = tm.tm_sec;
1575  result->subsecx = subsecx;
1576  result->wday = tm.tm_wday;
1577  result->yday = tm.tm_yday+1;
1578  result->isdst = tm.tm_isdst;
1579  result->utc_offset = LONG2NUM(gmtoff);
1580  result->zone = zone;
1581  return result;
1582  }
1583  }
1584 
1585  if (!gmtimew(timew, result))
1586  return NULL;
1587 
1588  offset = guess_local_offset(result, &isdst, &zone);
1589 
1590  if (!gmtimew(wadd(timew, rb_time_magnify(v2w(offset))), result))
1591  return NULL;
1592 
1593  result->utc_offset = offset;
1594  result->isdst = isdst;
1595  result->zone = zone;
1596 
1597  return result;
1598 }
1599 
1600 PACKED_STRUCT_UNALIGNED(struct time_object {
1601  wideval_t timew; /* time_t value * TIME_SCALE. possibly Rational. */
1602  struct vtm vtm;
1603  uint8_t gmt:3; /* 0:localtime 1:utc 2:fixoff 3:init */
1604  uint8_t tm_got:1;
1605 });
1606 
1607 #define GetTimeval(obj, tobj) ((tobj) = get_timeval(obj))
1608 #define GetNewTimeval(obj, tobj) ((tobj) = get_new_timeval(obj))
1609 
1610 #define IsTimeval(obj) rb_typeddata_is_kind_of((obj), &time_data_type)
1611 #define TIME_INIT_P(tobj) ((tobj)->gmt != TO_GMT_INITVAL)
1612 
1613 #define TIME_UTC_P(tobj) ((tobj)->gmt == 1)
1614 #define TIME_SET_UTC(tobj) ((tobj)->gmt = 1)
1615 
1616 #define TIME_LOCALTIME_P(tobj) ((tobj)->gmt == 0)
1617 #define TIME_SET_LOCALTIME(tobj) ((tobj)->gmt = 0)
1618 
1619 #define TIME_FIXOFF_P(tobj) ((tobj)->gmt == 2)
1620 #define TIME_SET_FIXOFF(tobj, off) \
1621  ((tobj)->gmt = 2, \
1622  (tobj)->vtm.utc_offset = (off), \
1623  (tobj)->vtm.zone = NULL)
1624 
1625 #define TIME_COPY_GMT(tobj1, tobj2) \
1626  ((tobj1)->gmt = (tobj2)->gmt, \
1627  (tobj1)->vtm.utc_offset = (tobj2)->vtm.utc_offset, \
1628  (tobj1)->vtm.zone = (tobj2)->vtm.zone)
1629 
1630 static VALUE time_get_tm(VALUE, struct time_object *);
1631 #define MAKE_TM(time, tobj) \
1632  do { \
1633  if ((tobj)->tm_got == 0) { \
1634  time_get_tm((time), (tobj)); \
1635  } \
1636  } while (0)
1637 
1638 static void
1639 time_mark(void *ptr)
1640 {
1641  struct time_object *tobj = ptr;
1642  if (!FIXWV_P(tobj->timew))
1643  rb_gc_mark(w2v(tobj->timew));
1644  rb_gc_mark(tobj->vtm.year);
1645  rb_gc_mark(tobj->vtm.subsecx);
1646  rb_gc_mark(tobj->vtm.utc_offset);
1647 }
1648 
1649 static size_t
1650 time_memsize(const void *tobj)
1651 {
1652  return sizeof(struct time_object);
1653 }
1654 
1655 static const rb_data_type_t time_data_type = {
1656  "time",
1657  {time_mark, RUBY_TYPED_DEFAULT_FREE, time_memsize,},
1659 };
1660 
1661 static VALUE
1662 time_s_alloc(VALUE klass)
1663 {
1664  VALUE obj;
1665  struct time_object *tobj;
1666 
1667  obj = TypedData_Make_Struct(klass, struct time_object, &time_data_type, tobj);
1668  tobj->gmt = TO_GMT_INITVAL;
1669  tobj->tm_got=0;
1670  tobj->timew = WINT2FIXWV(0);
1671 
1672  return obj;
1673 }
1674 
1675 static struct time_object *
1676 get_timeval(VALUE obj)
1677 {
1678  struct time_object *tobj;
1679  TypedData_Get_Struct(obj, struct time_object, &time_data_type, tobj);
1680  if (!TIME_INIT_P(tobj)) {
1681  rb_raise(rb_eTypeError, "uninitialized %"PRIsVALUE, rb_obj_class(obj));
1682  }
1683  return tobj;
1684 }
1685 
1686 static struct time_object *
1687 get_new_timeval(VALUE obj)
1688 {
1689  struct time_object *tobj;
1690  TypedData_Get_Struct(obj, struct time_object, &time_data_type, tobj);
1691  if (TIME_INIT_P(tobj)) {
1692  rb_raise(rb_eTypeError, "already initialized %"PRIsVALUE, rb_obj_class(obj));
1693  }
1694  return tobj;
1695 }
1696 
1697 static void
1698 time_modify(VALUE time)
1699 {
1700  rb_check_frozen(time);
1701  rb_check_trusted(time);
1702 }
1703 
1704 static wideval_t
1705 timespec2timew(struct timespec *ts)
1706 {
1707  wideval_t timew;
1708 
1709  timew = rb_time_magnify(TIMET2WV(ts->tv_sec));
1710  if (ts->tv_nsec)
1711  timew = wadd(timew, wmulquoll(WINT2WV(ts->tv_nsec), TIME_SCALE, 1000000000));
1712  return timew;
1713 }
1714 
1715 static struct timespec
1716 timew2timespec(wideval_t timew)
1717 {
1718  VALUE subsecx;
1719  struct timespec ts;
1720  wideval_t timew2;
1721 
1722  if (timew_out_of_timet_range(timew))
1723  rb_raise(rb_eArgError, "time out of system range");
1724  split_second(timew, &timew2, &subsecx);
1725  ts.tv_sec = WV2TIMET(timew2);
1726  ts.tv_nsec = NUM2LONG(mulquov(subsecx, INT2FIX(1000000000), INT2FIX(TIME_SCALE)));
1727  return ts;
1728 }
1729 
1730 static struct timespec *
1731 timew2timespec_exact(wideval_t timew, struct timespec *ts)
1732 {
1733  VALUE subsecx;
1734  wideval_t timew2;
1735  VALUE nsecv;
1736 
1737  if (timew_out_of_timet_range(timew))
1738  return NULL;
1739  split_second(timew, &timew2, &subsecx);
1740  ts->tv_sec = WV2TIMET(timew2);
1741  nsecv = mulquov(subsecx, INT2FIX(1000000000), INT2FIX(TIME_SCALE));
1742  if (!FIXNUM_P(nsecv))
1743  return NULL;
1744  ts->tv_nsec = NUM2LONG(nsecv);
1745  return ts;
1746 }
1747 
1748 void
1750 {
1751 #ifdef HAVE_CLOCK_GETTIME
1752  if (clock_gettime(CLOCK_REALTIME, ts) == -1) {
1753  rb_sys_fail("clock_gettime");
1754  }
1755 #else
1756  {
1757  struct timeval tv;
1758  if (gettimeofday(&tv, 0) < 0) {
1759  rb_sys_fail("gettimeofday");
1760  }
1761  ts->tv_sec = tv.tv_sec;
1762  ts->tv_nsec = tv.tv_usec * 1000;
1763  }
1764 #endif
1765 }
1766 
1767 static VALUE
1768 time_init_0(VALUE time)
1769 {
1770  struct time_object *tobj;
1771  struct timespec ts;
1772 
1773  time_modify(time);
1774  GetNewTimeval(time, tobj);
1775  tobj->gmt = 0;
1776  tobj->tm_got=0;
1777  tobj->timew = WINT2FIXWV(0);
1778  rb_timespec_now(&ts);
1779  tobj->timew = timespec2timew(&ts);
1780 
1781  return time;
1782 }
1783 
1784 static VALUE
1785 time_set_utc_offset(VALUE time, VALUE off)
1786 {
1787  struct time_object *tobj;
1788  off = num_exact(off);
1789 
1790  time_modify(time);
1791  GetTimeval(time, tobj);
1792 
1793  tobj->tm_got = 0;
1794  TIME_SET_FIXOFF(tobj, off);
1795 
1796  return time;
1797 }
1798 
1799 static void
1800 vtm_add_offset(struct vtm *vtm, VALUE off)
1801 {
1802  int sign;
1803  VALUE subsec, v;
1804  int sec, min, hour;
1805  int day;
1806 
1807  vtm->utc_offset = subv(vtm->utc_offset, off);
1808 
1809  if (lt(off, INT2FIX(0))) {
1810  sign = -1;
1811  off = neg(off);
1812  }
1813  else {
1814  sign = 1;
1815  }
1816  divmodv(off, INT2FIX(1), &off, &subsec);
1817  divmodv(off, INT2FIX(60), &off, &v);
1818  sec = NUM2INT(v);
1819  divmodv(off, INT2FIX(60), &off, &v);
1820  min = NUM2INT(v);
1821  divmodv(off, INT2FIX(24), &off, &v);
1822  hour = NUM2INT(v);
1823 
1824  if (sign < 0) {
1825  subsec = neg(subsec);
1826  sec = -sec;
1827  min = -min;
1828  hour = -hour;
1829  }
1830 
1831  day = 0;
1832 
1833  if (!rb_equal(subsec, INT2FIX(0))) {
1834  vtm->subsecx = addv(vtm->subsecx, w2v(rb_time_magnify(v2w(subsec))));
1835  if (lt(vtm->subsecx, INT2FIX(0))) {
1836  vtm->subsecx = addv(vtm->subsecx, INT2FIX(TIME_SCALE));
1837  sec -= 1;
1838  }
1839  if (le(INT2FIX(TIME_SCALE), vtm->subsecx)) {
1840  vtm->subsecx = subv(vtm->subsecx, INT2FIX(TIME_SCALE));
1841  sec += 1;
1842  }
1843  goto not_zero_sec;
1844  }
1845  if (sec) {
1846  not_zero_sec:
1847  /* If sec + subsec == 0, don't change vtm->sec.
1848  * It may be 60 which is a leap second. */
1849  sec += vtm->sec;
1850  if (sec < 0) {
1851  sec += 60;
1852  min -= 1;
1853  }
1854  if (60 <= sec) {
1855  sec -= 60;
1856  min += 1;
1857  }
1858  vtm->sec = sec;
1859  }
1860  if (min) {
1861  min += vtm->min;
1862  if (min < 0) {
1863  min += 60;
1864  hour -= 1;
1865  }
1866  if (60 <= min) {
1867  min -= 60;
1868  hour += 1;
1869  }
1870  vtm->min = min;
1871  }
1872  if (hour) {
1873  hour += vtm->hour;
1874  if (hour < 0) {
1875  hour += 24;
1876  day = -1;
1877  }
1878  if (24 <= hour) {
1879  hour -= 24;
1880  day = 1;
1881  }
1882  vtm->hour = hour;
1883  }
1884 
1885  if (day) {
1886  if (day < 0) {
1887  if (vtm->mon == 1 && vtm->mday == 1) {
1888  vtm->mday = 31;
1889  vtm->mon = 12; /* December */
1890  vtm->year = subv(vtm->year, INT2FIX(1));
1891  vtm->yday = leap_year_v_p(vtm->year) ? 366 : 365;
1892  }
1893  else if (vtm->mday == 1) {
1894  const int *days_in_month = leap_year_v_p(vtm->year) ?
1895  leap_year_days_in_month :
1896  common_year_days_in_month;
1897  vtm->mon--;
1898  vtm->mday = days_in_month[vtm->mon-1];
1899  vtm->yday--;
1900  }
1901  else {
1902  vtm->mday--;
1903  vtm->yday--;
1904  }
1905  vtm->wday = (vtm->wday + 6) % 7;
1906  }
1907  else {
1908  int leap = leap_year_v_p(vtm->year);
1909  if (vtm->mon == 12 && vtm->mday == 31) {
1910  vtm->year = addv(vtm->year, INT2FIX(1));
1911  vtm->mon = 1; /* January */
1912  vtm->mday = 1;
1913  vtm->yday = 1;
1914  }
1915  else if (vtm->mday == (leap ? leap_year_days_in_month :
1916  common_year_days_in_month)[vtm->mon-1]) {
1917  vtm->mon++;
1918  vtm->mday = 1;
1919  vtm->yday++;
1920  }
1921  else {
1922  vtm->mday++;
1923  vtm->yday++;
1924  }
1925  vtm->wday = (vtm->wday + 1) % 7;
1926  }
1927  }
1928 }
1929 
1930 static VALUE
1931 utc_offset_arg(VALUE arg)
1932 {
1933  VALUE tmp;
1934  if (!NIL_P(tmp = rb_check_string_type(arg))) {
1935  int n = 0;
1936  char *s = RSTRING_PTR(tmp);
1937  if (!rb_enc_str_asciicompat_p(tmp)) {
1938  invalid_utc_offset:
1939  rb_raise(rb_eArgError, "\"+HH:MM\" or \"-HH:MM\" expected for utc_offset");
1940  }
1941  switch (RSTRING_LEN(tmp)) {
1942  case 9:
1943  if (s[6] != ':') goto invalid_utc_offset;
1944  if (!ISDIGIT(s[7]) || !ISDIGIT(s[8])) goto invalid_utc_offset;
1945  n += (s[7] * 10 + s[8] - '0' * 11);
1946  case 6:
1947  if (s[0] != '+' && s[0] != '-') goto invalid_utc_offset;
1948  if (!ISDIGIT(s[1]) || !ISDIGIT(s[2])) goto invalid_utc_offset;
1949  if (s[3] != ':') goto invalid_utc_offset;
1950  if (!ISDIGIT(s[4]) || !ISDIGIT(s[5])) goto invalid_utc_offset;
1951  if (s[4] > '5') goto invalid_utc_offset;
1952  break;
1953  default:
1954  goto invalid_utc_offset;
1955  }
1956  n += (s[1] * 10 + s[2] - '0' * 11) * 3600;
1957  n += (s[4] * 10 + s[5] - '0' * 11) * 60;
1958  if (s[0] == '-')
1959  n = -n;
1960  return INT2FIX(n);
1961  }
1962  else {
1963  return num_exact(arg);
1964  }
1965 }
1966 
1967 static VALUE
1968 time_init_1(int argc, VALUE *argv, VALUE time)
1969 {
1970  struct vtm vtm;
1971  VALUE v[7];
1972  struct time_object *tobj;
1973 
1974  vtm.wday = VTM_WDAY_INITVAL;
1975  vtm.yday = 0;
1976  vtm.zone = "";
1977 
1978  /* year mon mday hour min sec off */
1979  rb_scan_args(argc, argv, "16", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6]);
1980 
1981  vtm.year = obj2vint(v[0]);
1982 
1983  vtm.mon = NIL_P(v[1]) ? 1 : month_arg(v[1]);
1984 
1985  vtm.mday = NIL_P(v[2]) ? 1 : obj2ubits(v[2], 5);
1986 
1987  vtm.hour = NIL_P(v[3]) ? 0 : obj2ubits(v[3], 5);
1988 
1989  vtm.min = NIL_P(v[4]) ? 0 : obj2ubits(v[4], 6);
1990 
1991  if (NIL_P(v[5])) {
1992  vtm.sec = 0;
1993  vtm.subsecx = INT2FIX(0);
1994  }
1995  else {
1996  VALUE subsecx;
1997  vtm.sec = obj2subsecx(v[5], &subsecx);
1998  vtm.subsecx = subsecx;
1999  }
2000 
2001  vtm.isdst = VTM_ISDST_INITVAL;
2002  vtm.utc_offset = Qnil;
2003  if (!NIL_P(v[6])) {
2004  VALUE arg = v[6];
2005  if (arg == ID2SYM(rb_intern("dst")))
2006  vtm.isdst = 1;
2007  else if (arg == ID2SYM(rb_intern("std")))
2008  vtm.isdst = 0;
2009  else
2010  vtm.utc_offset = utc_offset_arg(arg);
2011  }
2012 
2013  validate_vtm(&vtm);
2014 
2015  time_modify(time);
2016  GetNewTimeval(time, tobj);
2017  tobj->gmt = 0;
2018  tobj->tm_got=0;
2019  tobj->timew = WINT2FIXWV(0);
2020 
2021  if (!NIL_P(vtm.utc_offset)) {
2022  VALUE off = vtm.utc_offset;
2023  vtm_add_offset(&vtm, neg(off));
2024  vtm.utc_offset = Qnil;
2025  tobj->timew = timegmw(&vtm);
2026  return time_set_utc_offset(time, off);
2027  }
2028  else {
2029  tobj->timew = timelocalw(&vtm);
2030  return time_localtime(time);
2031  }
2032 }
2033 
2034 
2035 /*
2036  * call-seq:
2037  * Time.new -> time
2038  * Time.new(year, month=nil, day=nil, hour=nil, min=nil, sec=nil, utc_offset=nil) -> time
2039  *
2040  * Returns a Time object.
2041  *
2042  * It is initialized to the current system time if no argument is given.
2043  *
2044  * *Note:* The new object will use the resolution available on your
2045  * system clock, and may include fractional seconds.
2046  *
2047  * If one or more arguments specified, the time is initialized to the specified
2048  * time.
2049  *
2050  * +sec+ may have fraction if it is a rational.
2051  *
2052  * +utc_offset+ is the offset from UTC.
2053  * It can be a string such as "+09:00" or a number of seconds such as 32400.
2054  *
2055  * a = Time.new #=> 2007-11-19 07:50:02 -0600
2056  * b = Time.new #=> 2007-11-19 07:50:02 -0600
2057  * a == b #=> false
2058  * "%.6f" % a.to_f #=> "1195480202.282373"
2059  * "%.6f" % b.to_f #=> "1195480202.283415"
2060  *
2061  * Time.new(2008,6,21, 13,30,0, "+09:00") #=> 2008-06-21 13:30:00 +0900
2062  *
2063  * # A trip for RubyConf 2007
2064  * t1 = Time.new(2007,11,1,15,25,0, "+09:00") # JST (Narita)
2065  * t2 = Time.new(2007,11,1,12, 5,0, "-05:00") # CDT (Minneapolis)
2066  * t3 = Time.new(2007,11,1,13,25,0, "-05:00") # CDT (Minneapolis)
2067  * t4 = Time.new(2007,11,1,16,53,0, "-04:00") # EDT (Charlotte)
2068  * t5 = Time.new(2007,11,5, 9,24,0, "-05:00") # EST (Charlotte)
2069  * t6 = Time.new(2007,11,5,11,21,0, "-05:00") # EST (Detroit)
2070  * t7 = Time.new(2007,11,5,13,45,0, "-05:00") # EST (Detroit)
2071  * t8 = Time.new(2007,11,6,17,10,0, "+09:00") # JST (Narita)
2072  * p((t2-t1)/3600.0) #=> 10.666666666666666
2073  * p((t4-t3)/3600.0) #=> 2.466666666666667
2074  * p((t6-t5)/3600.0) #=> 1.95
2075  * p((t8-t7)/3600.0) #=> 13.416666666666666
2076  *
2077  */
2078 
2079 static VALUE
2080 time_init(int argc, VALUE *argv, VALUE time)
2081 {
2082  if (argc == 0)
2083  return time_init_0(time);
2084  else
2085  return time_init_1(argc, argv, time);
2086 }
2087 
2088 static void
2089 time_overflow_p(time_t *secp, long *nsecp)
2090 {
2091  time_t sec = *secp;
2092  long nsec = *nsecp;
2093  long sec2;
2094 
2095  if (nsec >= 1000000000) { /* nsec positive overflow */
2096  sec2 = nsec / 1000000000;
2097  if (TIMET_MAX - sec2 < sec) {
2098  rb_raise(rb_eRangeError, "out of Time range");
2099  }
2100  nsec -= sec2 * 1000000000;
2101  sec += sec2;
2102  }
2103  else if (nsec < 0) { /* nsec negative overflow */
2104  sec2 = NDIV(nsec,1000000000); /* negative div */
2105  if (sec < TIMET_MIN - sec2) {
2106  rb_raise(rb_eRangeError, "out of Time range");
2107  }
2108  nsec -= sec2 * 1000000000;
2109  sec += sec2;
2110  }
2111 #ifndef NEGATIVE_TIME_T
2112  if (sec < 0)
2113  rb_raise(rb_eArgError, "time must be positive");
2114 #endif
2115  *secp = sec;
2116  *nsecp = nsec;
2117 }
2118 
2119 static wideval_t
2120 nsec2timew(time_t sec, long nsec)
2121 {
2122  struct timespec ts;
2123  time_overflow_p(&sec, &nsec);
2124  ts.tv_sec = sec;
2125  ts.tv_nsec = nsec;
2126  return timespec2timew(&ts);
2127 }
2128 
2129 static VALUE
2130 time_new_timew(VALUE klass, wideval_t timew)
2131 {
2132  VALUE time = time_s_alloc(klass);
2133  struct time_object *tobj;
2134 
2135  tobj = DATA_PTR(time); /* skip type check */
2136  tobj->gmt = 0;
2137  tobj->timew = timew;
2138 
2139  return time;
2140 }
2141 
2142 VALUE
2143 rb_time_new(time_t sec, long usec)
2144 {
2145  wideval_t timew;
2146 
2147  if (usec >= 1000000) {
2148  long sec2 = usec / 1000000;
2149  if (sec > TIMET_MAX - sec2) {
2150  rb_raise(rb_eRangeError, "out of Time range");
2151  }
2152  usec -= sec2 * 1000000;
2153  sec += sec2;
2154  }
2155  else if (usec < 0) {
2156  long sec2 = NDIV(usec,1000000); /* negative div */
2157  if (sec < TIMET_MIN - sec2) {
2158  rb_raise(rb_eRangeError, "out of Time range");
2159  }
2160  usec -= sec2 * 1000000;
2161  sec += sec2;
2162  }
2163 
2164  timew = nsec2timew(sec, usec * 1000);
2165  return time_new_timew(rb_cTime, timew);
2166 }
2167 
2168 /* returns localtime time object */
2169 VALUE
2170 rb_time_nano_new(time_t sec, long nsec)
2171 {
2172  return time_new_timew(rb_cTime, nsec2timew(sec, nsec));
2173 }
2174 
2180 VALUE
2181 rb_time_timespec_new(const struct timespec *ts, int offset)
2182 {
2183  struct time_object *tobj;
2184  VALUE time = time_new_timew(rb_cTime, nsec2timew(ts->tv_sec, ts->tv_nsec));
2185 
2186  if (-86400 < offset && offset < 86400) { /* fixoff */
2187  GetTimeval(time, tobj);
2188  TIME_SET_FIXOFF(tobj, INT2FIX(offset));
2189  }
2190  else if (offset == INT_MAX) { /* localtime */
2191  }
2192  else if (offset == INT_MAX-1) { /* UTC */
2193  GetTimeval(time, tobj);
2194  TIME_SET_UTC(tobj);
2195  }
2196  else {
2197  rb_raise(rb_eArgError, "utc_offset out of range");
2198  }
2199 
2200  return time;
2201 }
2202 
2203 VALUE
2205 {
2206  VALUE time = time_new_timew(rb_cTime, rb_time_magnify(v2w(timev)));
2207 
2208  if (!NIL_P(off)) {
2209  off = utc_offset_arg(off);
2210  validate_utc_offset(off);
2211  time_set_utc_offset(time, off);
2212  return time;
2213  }
2214 
2215  return time;
2216 }
2217 
2218 static struct timespec
2219 time_timespec(VALUE num, int interval)
2220 {
2221  struct timespec t;
2222  const char *const tstr = interval ? "time interval" : "time";
2223  VALUE i, f, ary;
2224 
2225 #ifndef NEGATIVE_TIME_T
2226  interval = 1;
2227 #endif
2228 
2229  if (FIXNUM_P(num)) {
2230  t.tv_sec = NUM2TIMET(num);
2231  if (interval && t.tv_sec < 0)
2232  rb_raise(rb_eArgError, "%s must be positive", tstr);
2233  t.tv_nsec = 0;
2234  }
2235  else if (RB_FLOAT_TYPE_P(num)) {
2236  if (interval && RFLOAT_VALUE(num) < 0.0)
2237  rb_raise(rb_eArgError, "%s must be positive", tstr);
2238  else {
2239  double f, d;
2240 
2241  d = modf(RFLOAT_VALUE(num), &f);
2242  if (d >= 0) {
2243  t.tv_nsec = (int)(d*1e9+0.5);
2244  if (t.tv_nsec >= 1000000000) {
2245  t.tv_nsec -= 1000000000;
2246  f += 1;
2247  }
2248  }
2249  else if ((t.tv_nsec = (int)(-d*1e9+0.5)) > 0) {
2250  t.tv_nsec = 1000000000 - t.tv_nsec;
2251  f -= 1;
2252  }
2253  t.tv_sec = (time_t)f;
2254  if (f != t.tv_sec) {
2255  rb_raise(rb_eRangeError, "%f out of Time range", RFLOAT_VALUE(num));
2256  }
2257  }
2258  }
2259  else if (RB_TYPE_P(num, T_BIGNUM)) {
2260  t.tv_sec = NUM2TIMET(num);
2261  if (interval && t.tv_sec < 0)
2262  rb_raise(rb_eArgError, "%s must be positive", tstr);
2263  t.tv_nsec = 0;
2264  }
2265  else {
2266  i = INT2FIX(1);
2267  ary = rb_check_funcall(num, id_divmod, 1, &i);
2268  if (ary != Qundef && !NIL_P(ary = rb_check_array_type(ary))) {
2269  i = rb_ary_entry(ary, 0);
2270  f = rb_ary_entry(ary, 1);
2271  t.tv_sec = NUM2TIMET(i);
2272  if (interval && t.tv_sec < 0)
2273  rb_raise(rb_eArgError, "%s must be positive", tstr);
2274  f = rb_funcall(f, '*', 1, INT2FIX(1000000000));
2275  t.tv_nsec = NUM2LONG(f);
2276  }
2277  else {
2278  rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into %s",
2279  rb_obj_class(num), tstr);
2280  }
2281  }
2282  return t;
2283 }
2284 
2285 static struct timeval
2286 time_timeval(VALUE num, int interval)
2287 {
2288  struct timespec ts;
2289  struct timeval tv;
2290 
2291  ts = time_timespec(num, interval);
2292  tv.tv_sec = (TYPEOF_TIMEVAL_TV_SEC)ts.tv_sec;
2293  tv.tv_usec = (TYPEOF_TIMEVAL_TV_USEC)(ts.tv_nsec / 1000);
2294 
2295  return tv;
2296 }
2297 
2298 struct timeval
2300 {
2301  return time_timeval(num, TRUE);
2302 }
2303 
2304 struct timeval
2305 rb_time_timeval(VALUE time)
2306 {
2307  struct time_object *tobj;
2308  struct timeval t;
2309  struct timespec ts;
2310 
2311  if (IsTimeval(time)) {
2312  GetTimeval(time, tobj);
2313  ts = timew2timespec(tobj->timew);
2315  t.tv_usec = (TYPEOF_TIMEVAL_TV_USEC)(ts.tv_nsec / 1000);
2316  return t;
2317  }
2318  return time_timeval(time, FALSE);
2319 }
2320 
2321 struct timespec
2322 rb_time_timespec(VALUE time)
2323 {
2324  struct time_object *tobj;
2325  struct timespec t;
2326 
2327  if (IsTimeval(time)) {
2328  GetTimeval(time, tobj);
2329  t = timew2timespec(tobj->timew);
2330  return t;
2331  }
2332  return time_timespec(time, FALSE);
2333 }
2334 
2335 /*
2336  * call-seq:
2337  * Time.now -> time
2338  *
2339  * Creates a new Time object for the current time.
2340  * This is same as Time.new without arguments.
2341  *
2342  * Time.now #=> 2009-06-24 12:39:54 +0900
2343  */
2344 
2345 static VALUE
2346 time_s_now(VALUE klass)
2347 {
2348  return rb_class_new_instance(0, NULL, klass);
2349 }
2350 
2351 static int
2352 get_scale(VALUE unit) {
2353  if (unit == ID2SYM(id_nanosecond) || unit == ID2SYM(id_nsec)) {
2354  return 1000000000;
2355  }
2356  else if (unit == ID2SYM(id_microsecond) || unit == ID2SYM(id_usec)) {
2357  return 1000000;
2358  }
2359  else if (unit == ID2SYM(id_millisecond)) {
2360  return 1000;
2361  }
2362  else {
2363  rb_raise(rb_eArgError, "unexpected unit: %"PRIsVALUE, unit);
2364  }
2365 }
2366 
2367 /*
2368  * call-seq:
2369  * Time.at(time) -> time
2370  * Time.at(seconds_with_frac) -> time
2371  * Time.at(seconds, microseconds_with_frac) -> time
2372  * Time.at(seconds, milliseconds, :millisecond) -> time
2373  * Time.at(seconds, microseconds, :usec) -> time
2374  * Time.at(seconds, microseconds, :microsecond) -> time
2375  * Time.at(seconds, nanoseconds, :nsec) -> time
2376  * Time.at(seconds, nanoseconds, :nanosecond) -> time
2377  *
2378  * Creates a new Time object with the value given by +time+,
2379  * the given number of +seconds_with_frac+, or
2380  * +seconds+ and +microseconds_with_frac+ since the Epoch.
2381  * +seconds_with_frac+ and +microseconds_with_frac+
2382  * can be an Integer, Float, Rational, or other Numeric.
2383  * non-portable feature allows the offset to be negative on some systems.
2384  *
2385  * If a numeric argument is given, the result is in local time.
2386  *
2387  * Time.at(0) #=> 1969-12-31 18:00:00 -0600
2388  * Time.at(Time.at(0)) #=> 1969-12-31 18:00:00 -0600
2389  * Time.at(946702800) #=> 1999-12-31 23:00:00 -0600
2390  * Time.at(-284061600) #=> 1960-12-31 00:00:00 -0600
2391  * Time.at(946684800.2).usec #=> 200000
2392  * Time.at(946684800, 123456.789).nsec #=> 123456789
2393  * Time.at(946684800, 123456789, :nsec).nsec #=> 123456789
2394  */
2395 
2396 static VALUE
2397 time_s_at(int argc, VALUE *argv, VALUE klass)
2398 {
2399  VALUE time, t, unit = Qundef;
2400  wideval_t timew;
2401 
2402  if (rb_scan_args(argc, argv, "12", &time, &t, &unit) >= 2) {
2403  int scale = argc == 3 ? get_scale(unit) : 1000000;
2404  time = num_exact(time);
2405  t = num_exact(t);
2406  timew = wadd(rb_time_magnify(v2w(time)), wmulquoll(v2w(t), TIME_SCALE, scale));
2407  t = time_new_timew(klass, timew);
2408  }
2409  else if (IsTimeval(time)) {
2410  struct time_object *tobj, *tobj2;
2411  GetTimeval(time, tobj);
2412  t = time_new_timew(klass, tobj->timew);
2413  GetTimeval(t, tobj2);
2414  TIME_COPY_GMT(tobj2, tobj);
2415  }
2416  else {
2417  timew = rb_time_magnify(v2w(num_exact(time)));
2418  t = time_new_timew(klass, timew);
2419  }
2420 
2421  return t;
2422 }
2423 
2424 static const char months[][4] = {
2425  "jan", "feb", "mar", "apr", "may", "jun",
2426  "jul", "aug", "sep", "oct", "nov", "dec",
2427 };
2428 
2429 static int
2430 obj2int(VALUE obj)
2431 {
2432  if (RB_TYPE_P(obj, T_STRING)) {
2433  obj = rb_str_to_inum(obj, 10, FALSE);
2434  }
2435 
2436  return NUM2INT(obj);
2437 }
2438 
2439 static uint32_t
2440 obj2ubits(VALUE obj, size_t bits)
2441 {
2442  static const uint32_t u32max = (uint32_t)-1;
2443  const uint32_t usable_mask = ~(u32max << bits);
2444  uint32_t rv;
2445  int tmp = obj2int(obj);
2446 
2447  if (tmp < 0)
2448  rb_raise(rb_eArgError, "argument out of range");
2449  rv = tmp;
2450  if ((rv & usable_mask) != rv)
2451  rb_raise(rb_eArgError, "argument out of range");
2452  return rv;
2453 }
2454 
2455 static VALUE
2456 obj2vint(VALUE obj)
2457 {
2458  if (RB_TYPE_P(obj, T_STRING)) {
2459  obj = rb_str_to_inum(obj, 10, FALSE);
2460  }
2461  else {
2462  obj = rb_to_int(obj);
2463  }
2464 
2465  return obj;
2466 }
2467 
2468 static uint32_t
2469 obj2subsecx(VALUE obj, VALUE *subsecx)
2470 {
2471  VALUE subsec;
2472 
2473  if (RB_TYPE_P(obj, T_STRING)) {
2474  obj = rb_str_to_inum(obj, 10, FALSE);
2475  *subsecx = INT2FIX(0);
2476  }
2477  else {
2478  divmodv(num_exact(obj), INT2FIX(1), &obj, &subsec);
2479  *subsecx = w2v(rb_time_magnify(v2w(subsec)));
2480  }
2481  return obj2ubits(obj, 6); /* vtm->sec */
2482 }
2483 
2484 static VALUE
2485 usec2subsecx(VALUE obj)
2486 {
2487  if (RB_TYPE_P(obj, T_STRING)) {
2488  obj = rb_str_to_inum(obj, 10, FALSE);
2489  }
2490 
2491  return mulquov(num_exact(obj), INT2FIX(TIME_SCALE), INT2FIX(1000000));
2492 }
2493 
2494 static uint32_t
2495 month_arg(VALUE arg)
2496 {
2497  int i, mon;
2498 
2499  VALUE s = rb_check_string_type(arg);
2500  if (!NIL_P(s) && RSTRING_LEN(s) > 0) {
2501  mon = 0;
2502  for (i=0; i<12; i++) {
2503  if (RSTRING_LEN(s) == 3 &&
2504  STRNCASECMP(months[i], RSTRING_PTR(s), 3) == 0) {
2505  mon = i+1;
2506  break;
2507  }
2508  }
2509  if (mon == 0) {
2510  char c = RSTRING_PTR(s)[0];
2511 
2512  if ('0' <= c && c <= '9') {
2513  mon = obj2ubits(s, 4);
2514  }
2515  }
2516  }
2517  else {
2518  mon = obj2ubits(arg, 4);
2519  }
2520  return mon;
2521 }
2522 
2523 static VALUE
2524 validate_utc_offset(VALUE utc_offset)
2525 {
2526  if (le(utc_offset, INT2FIX(-86400)) || ge(utc_offset, INT2FIX(86400)))
2527  rb_raise(rb_eArgError, "utc_offset out of range");
2528  return utc_offset;
2529 }
2530 
2531 static VALUE
2532 validate_zone_name(VALUE zone_name)
2533 {
2534  StringValueCStr(zone_name);
2535  return zone_name;
2536 }
2537 
2538 static void
2539 validate_vtm(struct vtm *vtm)
2540 {
2541 #define validate_vtm_range(mem, b, e) \
2542  ((vtm->mem < b || vtm->mem > e) ? \
2543  rb_raise(rb_eArgError, #mem" out of range") : (void)0)
2544  validate_vtm_range(mon, 1, 12);
2545  validate_vtm_range(mday, 1, 31);
2546  validate_vtm_range(hour, 0, 24);
2547  validate_vtm_range(min, 0, (vtm->hour == 24 ? 0 : 59));
2548  validate_vtm_range(sec, 0, (vtm->hour == 24 ? 0 : 60));
2549  if (lt(vtm->subsecx, INT2FIX(0)) || ge(vtm->subsecx, INT2FIX(TIME_SCALE)))
2550  rb_raise(rb_eArgError, "subsecx out of range");
2551  if (!NIL_P(vtm->utc_offset)) validate_utc_offset(vtm->utc_offset);
2552 #undef validate_vtm_range
2553 }
2554 
2555 static void
2556 time_arg(int argc, VALUE *argv, struct vtm *vtm)
2557 {
2558  VALUE v[8];
2559  VALUE subsecx = INT2FIX(0);
2560 
2561  vtm->year = INT2FIX(0);
2562  vtm->mon = 0;
2563  vtm->mday = 0;
2564  vtm->hour = 0;
2565  vtm->min = 0;
2566  vtm->sec = 0;
2567  vtm->subsecx = INT2FIX(0);
2568  vtm->utc_offset = Qnil;
2569  vtm->wday = 0;
2570  vtm->yday = 0;
2571  vtm->isdst = 0;
2572  vtm->zone = "";
2573 
2574  if (argc == 10) {
2575  v[0] = argv[5];
2576  v[1] = argv[4];
2577  v[2] = argv[3];
2578  v[3] = argv[2];
2579  v[4] = argv[1];
2580  v[5] = argv[0];
2581  v[6] = Qnil;
2582  vtm->isdst = RTEST(argv[8]) ? 1 : 0;
2583  }
2584  else {
2585  rb_scan_args(argc, argv, "17", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6],&v[7]);
2586  /* v[6] may be usec or zone (parsedate) */
2587  /* v[7] is wday (parsedate; ignored) */
2588  vtm->wday = VTM_WDAY_INITVAL;
2589  vtm->isdst = VTM_ISDST_INITVAL;
2590  }
2591 
2592  vtm->year = obj2vint(v[0]);
2593 
2594  if (NIL_P(v[1])) {
2595  vtm->mon = 1;
2596  }
2597  else {
2598  vtm->mon = month_arg(v[1]);
2599  }
2600 
2601  if (NIL_P(v[2])) {
2602  vtm->mday = 1;
2603  }
2604  else {
2605  vtm->mday = obj2ubits(v[2], 5);
2606  }
2607 
2608  vtm->hour = NIL_P(v[3])?0:obj2ubits(v[3], 5);
2609 
2610  vtm->min = NIL_P(v[4])?0:obj2ubits(v[4], 6);
2611 
2612  if (!NIL_P(v[6]) && argc == 7) {
2613  vtm->sec = NIL_P(v[5])?0:obj2ubits(v[5],6);
2614  subsecx = usec2subsecx(v[6]);
2615  }
2616  else {
2617  /* when argc == 8, v[6] is timezone, but ignored */
2618  if (NIL_P(v[5])) {
2619  vtm->sec = 0;
2620  }
2621  else {
2622  vtm->sec = obj2subsecx(v[5], &subsecx);
2623  }
2624  }
2625  vtm->subsecx = subsecx;
2626 
2627  validate_vtm(vtm);
2628  RB_GC_GUARD(subsecx);
2629 }
2630 
2631 static int
2632 leap_year_p(long y)
2633 {
2634  return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0);
2635 }
2636 
2637 static time_t
2638 timegm_noleapsecond(struct tm *tm)
2639 {
2640  long tm_year = tm->tm_year;
2641  int tm_yday = tm->tm_mday;
2642  if (leap_year_p(tm_year + 1900))
2643  tm_yday += leap_year_yday_offset[tm->tm_mon];
2644  else
2645  tm_yday += common_year_yday_offset[tm->tm_mon];
2646 
2647  /*
2648  * `Seconds Since the Epoch' in SUSv3:
2649  * tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
2650  * (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
2651  * ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
2652  */
2653  return tm->tm_sec + tm->tm_min*60 + tm->tm_hour*3600 +
2654  (time_t)(tm_yday +
2655  (tm_year-70)*365 +
2656  DIV(tm_year-69,4) -
2657  DIV(tm_year-1,100) +
2658  DIV(tm_year+299,400))*86400;
2659 }
2660 
2661 #if 0
2662 #define DEBUG_FIND_TIME_NUMGUESS
2663 #define DEBUG_GUESSRANGE
2664 #endif
2665 
2666 #ifdef DEBUG_GUESSRANGE
2667 #define DEBUG_REPORT_GUESSRANGE fprintf(stderr, "find time guess range: %ld - %ld : %"PRI_TIMET_PREFIX"u\n", guess_lo, guess_hi, (unsigned_time_t)(guess_hi-guess_lo))
2668 #else
2669 #define DEBUG_REPORT_GUESSRANGE
2670 #endif
2671 
2672 #ifdef DEBUG_FIND_TIME_NUMGUESS
2673 #define DEBUG_FIND_TIME_NUMGUESS_INC find_time_numguess++,
2674 static unsigned long long find_time_numguess;
2675 
2676 static VALUE find_time_numguess_getter(void)
2677 {
2678  return ULL2NUM(find_time_numguess);
2679 }
2680 #else
2681 #define DEBUG_FIND_TIME_NUMGUESS_INC
2682 #endif
2683 
2684 static const char *
2685 find_time_t(struct tm *tptr, int utc_p, time_t *tp)
2686 {
2687  time_t guess, guess0, guess_lo, guess_hi;
2688  struct tm *tm, tm0, tm_lo, tm_hi;
2689  int d;
2690  int find_dst;
2691  struct tm result;
2692  int status;
2693  int tptr_tm_yday;
2694 
2695 #define GUESS(p) (DEBUG_FIND_TIME_NUMGUESS_INC (utc_p ? gmtime_with_leapsecond((p), &result) : LOCALTIME((p), result)))
2696 
2697  guess_lo = TIMET_MIN;
2698  guess_hi = TIMET_MAX;
2699 
2700  find_dst = 0 < tptr->tm_isdst;
2701 
2702 #if defined(HAVE_MKTIME)
2703  tm0 = *tptr;
2704  if (!utc_p && (guess = mktime(&tm0)) != -1) {
2705  tm = GUESS(&guess);
2706  if (tm && tmcmp(tptr, tm) == 0) {
2707  goto found;
2708  }
2709  }
2710 #endif
2711 
2712  tm0 = *tptr;
2713  if (tm0.tm_mon < 0) {
2714  tm0.tm_mon = 0;
2715  tm0.tm_mday = 1;
2716  tm0.tm_hour = 0;
2717  tm0.tm_min = 0;
2718  tm0.tm_sec = 0;
2719  }
2720  else if (11 < tm0.tm_mon) {
2721  tm0.tm_mon = 11;
2722  tm0.tm_mday = 31;
2723  tm0.tm_hour = 23;
2724  tm0.tm_min = 59;
2725  tm0.tm_sec = 60;
2726  }
2727  else if (tm0.tm_mday < 1) {
2728  tm0.tm_mday = 1;
2729  tm0.tm_hour = 0;
2730  tm0.tm_min = 0;
2731  tm0.tm_sec = 0;
2732  }
2733  else if ((d = (leap_year_p(1900 + tm0.tm_year) ?
2734  leap_year_days_in_month :
2735  common_year_days_in_month)[tm0.tm_mon]) < tm0.tm_mday) {
2736  tm0.tm_mday = d;
2737  tm0.tm_hour = 23;
2738  tm0.tm_min = 59;
2739  tm0.tm_sec = 60;
2740  }
2741  else if (tm0.tm_hour < 0) {
2742  tm0.tm_hour = 0;
2743  tm0.tm_min = 0;
2744  tm0.tm_sec = 0;
2745  }
2746  else if (23 < tm0.tm_hour) {
2747  tm0.tm_hour = 23;
2748  tm0.tm_min = 59;
2749  tm0.tm_sec = 60;
2750  }
2751  else if (tm0.tm_min < 0) {
2752  tm0.tm_min = 0;
2753  tm0.tm_sec = 0;
2754  }
2755  else if (59 < tm0.tm_min) {
2756  tm0.tm_min = 59;
2757  tm0.tm_sec = 60;
2758  }
2759  else if (tm0.tm_sec < 0) {
2760  tm0.tm_sec = 0;
2761  }
2762  else if (60 < tm0.tm_sec) {
2763  tm0.tm_sec = 60;
2764  }
2765 
2767  guess0 = guess = timegm_noleapsecond(&tm0);
2768  tm = GUESS(&guess);
2769  if (tm) {
2770  d = tmcmp(tptr, tm);
2771  if (d == 0) { goto found; }
2772  if (d < 0) {
2773  guess_hi = guess;
2774  guess -= 24 * 60 * 60;
2775  }
2776  else {
2777  guess_lo = guess;
2778  guess += 24 * 60 * 60;
2779  }
2781  if (guess_lo < guess && guess < guess_hi && (tm = GUESS(&guess)) != NULL) {
2782  d = tmcmp(tptr, tm);
2783  if (d == 0) { goto found; }
2784  if (d < 0)
2785  guess_hi = guess;
2786  else
2787  guess_lo = guess;
2789  }
2790  }
2791 
2792  tm = GUESS(&guess_lo);
2793  if (!tm) goto error;
2794  d = tmcmp(tptr, tm);
2795  if (d < 0) goto out_of_range;
2796  if (d == 0) { guess = guess_lo; goto found; }
2797  tm_lo = *tm;
2798 
2799  tm = GUESS(&guess_hi);
2800  if (!tm) goto error;
2801  d = tmcmp(tptr, tm);
2802  if (d > 0) goto out_of_range;
2803  if (d == 0) { guess = guess_hi; goto found; }
2804  tm_hi = *tm;
2805 
2807 
2808  status = 1;
2809 
2810  while (guess_lo + 1 < guess_hi) {
2811  if (status == 0) {
2812  binsearch:
2813  guess = guess_lo / 2 + guess_hi / 2;
2814  if (guess <= guess_lo)
2815  guess = guess_lo + 1;
2816  else if (guess >= guess_hi)
2817  guess = guess_hi - 1;
2818  status = 1;
2819  }
2820  else {
2821  if (status == 1) {
2822  time_t guess0_hi = timegm_noleapsecond(&tm_hi);
2823  guess = guess_hi - (guess0_hi - guess0);
2824  if (guess == guess_hi) /* hh:mm:60 tends to cause this condition. */
2825  guess--;
2826  status = 2;
2827  }
2828  else if (status == 2) {
2829  time_t guess0_lo = timegm_noleapsecond(&tm_lo);
2830  guess = guess_lo + (guess0 - guess0_lo);
2831  if (guess == guess_lo)
2832  guess++;
2833  status = 0;
2834  }
2835  if (guess <= guess_lo || guess_hi <= guess) {
2836  /* Precious guess is invalid. try binary search. */
2837 #ifdef DEBUG_GUESSRANGE
2838  if (guess <= guess_lo) fprintf(stderr, "too small guess: %ld <= %ld\n", guess, guess_lo);
2839  if (guess_hi <= guess) fprintf(stderr, "too big guess: %ld <= %ld\n", guess_hi, guess);
2840 #endif
2841  goto binsearch;
2842  }
2843  }
2844 
2845  tm = GUESS(&guess);
2846  if (!tm) goto error;
2847 
2848  d = tmcmp(tptr, tm);
2849 
2850  if (d < 0) {
2851  guess_hi = guess;
2852  tm_hi = *tm;
2854  }
2855  else if (d > 0) {
2856  guess_lo = guess;
2857  tm_lo = *tm;
2859  }
2860  else {
2861  found:
2862  if (!utc_p) {
2863  /* If localtime is nonmonotonic, another result may exist. */
2864  time_t guess2;
2865  if (find_dst) {
2866  guess2 = guess - 2 * 60 * 60;
2867  tm = LOCALTIME(&guess2, result);
2868  if (tm) {
2869  if (tptr->tm_hour != (tm->tm_hour + 2) % 24 ||
2870  tptr->tm_min != tm->tm_min ||
2871  tptr->tm_sec != tm->tm_sec) {
2872  guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
2873  (tm->tm_min - tptr->tm_min) * 60 +
2874  (tm->tm_sec - tptr->tm_sec);
2875  if (tptr->tm_mday != tm->tm_mday)
2876  guess2 += 24 * 60 * 60;
2877  if (guess != guess2) {
2878  tm = LOCALTIME(&guess2, result);
2879  if (tm && tmcmp(tptr, tm) == 0) {
2880  if (guess < guess2)
2881  *tp = guess;
2882  else
2883  *tp = guess2;
2884  return NULL;
2885  }
2886  }
2887  }
2888  }
2889  }
2890  else {
2891  guess2 = guess + 2 * 60 * 60;
2892  tm = LOCALTIME(&guess2, result);
2893  if (tm) {
2894  if ((tptr->tm_hour + 2) % 24 != tm->tm_hour ||
2895  tptr->tm_min != tm->tm_min ||
2896  tptr->tm_sec != tm->tm_sec) {
2897  guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
2898  (tm->tm_min - tptr->tm_min) * 60 +
2899  (tm->tm_sec - tptr->tm_sec);
2900  if (tptr->tm_mday != tm->tm_mday)
2901  guess2 -= 24 * 60 * 60;
2902  if (guess != guess2) {
2903  tm = LOCALTIME(&guess2, result);
2904  if (tm && tmcmp(tptr, tm) == 0) {
2905  if (guess < guess2)
2906  *tp = guess2;
2907  else
2908  *tp = guess;
2909  return NULL;
2910  }
2911  }
2912  }
2913  }
2914  }
2915  }
2916  *tp = guess;
2917  return NULL;
2918  }
2919  }
2920 
2921  /* Given argument has no corresponding time_t. Let's extrapolate. */
2922  /*
2923  * `Seconds Since the Epoch' in SUSv3:
2924  * tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
2925  * (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
2926  * ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
2927  */
2928 
2929  tptr_tm_yday = calc_tm_yday(tptr->tm_year, tptr->tm_mon, tptr->tm_mday);
2930 
2931  *tp = guess_lo +
2932  ((tptr->tm_year - tm_lo.tm_year) * 365 +
2933  ((tptr->tm_year-69)/4) -
2934  ((tptr->tm_year-1)/100) +
2935  ((tptr->tm_year+299)/400) -
2936  ((tm_lo.tm_year-69)/4) +
2937  ((tm_lo.tm_year-1)/100) -
2938  ((tm_lo.tm_year+299)/400) +
2939  tptr_tm_yday -
2940  tm_lo.tm_yday) * 86400 +
2941  (tptr->tm_hour - tm_lo.tm_hour) * 3600 +
2942  (tptr->tm_min - tm_lo.tm_min) * 60 +
2943  (tptr->tm_sec - (tm_lo.tm_sec == 60 ? 59 : tm_lo.tm_sec));
2944 
2945  return NULL;
2946 
2947  out_of_range:
2948  return "time out of range";
2949 
2950  error:
2951  return "gmtime/localtime error";
2952 }
2953 
2954 static int
2955 vtmcmp(struct vtm *a, struct vtm *b)
2956 {
2957  if (ne(a->year, b->year))
2958  return lt(a->year, b->year) ? -1 : 1;
2959  else if (a->mon != b->mon)
2960  return a->mon < b->mon ? -1 : 1;
2961  else if (a->mday != b->mday)
2962  return a->mday < b->mday ? -1 : 1;
2963  else if (a->hour != b->hour)
2964  return a->hour < b->hour ? -1 : 1;
2965  else if (a->min != b->min)
2966  return a->min < b->min ? -1 : 1;
2967  else if (a->sec != b->sec)
2968  return a->sec < b->sec ? -1 : 1;
2969  else if (ne(a->subsecx, b->subsecx))
2970  return lt(a->subsecx, b->subsecx) ? -1 : 1;
2971  else
2972  return 0;
2973 }
2974 
2975 static int
2976 tmcmp(struct tm *a, struct tm *b)
2977 {
2978  if (a->tm_year != b->tm_year)
2979  return a->tm_year < b->tm_year ? -1 : 1;
2980  else if (a->tm_mon != b->tm_mon)
2981  return a->tm_mon < b->tm_mon ? -1 : 1;
2982  else if (a->tm_mday != b->tm_mday)
2983  return a->tm_mday < b->tm_mday ? -1 : 1;
2984  else if (a->tm_hour != b->tm_hour)
2985  return a->tm_hour < b->tm_hour ? -1 : 1;
2986  else if (a->tm_min != b->tm_min)
2987  return a->tm_min < b->tm_min ? -1 : 1;
2988  else if (a->tm_sec != b->tm_sec)
2989  return a->tm_sec < b->tm_sec ? -1 : 1;
2990  else
2991  return 0;
2992 }
2993 
2994 static VALUE
2995 time_utc_or_local(int argc, VALUE *argv, int utc_p, VALUE klass)
2996 {
2997  struct vtm vtm;
2998  VALUE time;
2999 
3000  time_arg(argc, argv, &vtm);
3001  if (utc_p)
3002  time = time_new_timew(klass, timegmw(&vtm));
3003  else
3004  time = time_new_timew(klass, timelocalw(&vtm));
3005  if (utc_p) return time_gmtime(time);
3006  return time_localtime(time);
3007 }
3008 
3009 /*
3010  * call-seq:
3011  * Time.utc(year) -> time
3012  * Time.utc(year, month) -> time
3013  * Time.utc(year, month, day) -> time
3014  * Time.utc(year, month, day, hour) -> time
3015  * Time.utc(year, month, day, hour, min) -> time
3016  * Time.utc(year, month, day, hour, min, sec_with_frac) -> time
3017  * Time.utc(year, month, day, hour, min, sec, usec_with_frac) -> time
3018  * Time.utc(sec, min, hour, day, month, year, dummy, dummy, dummy, dummy) -> time
3019  * Time.gm(year) -> time
3020  * Time.gm(year, month) -> time
3021  * Time.gm(year, month, day) -> time
3022  * Time.gm(year, month, day, hour) -> time
3023  * Time.gm(year, month, day, hour, min) -> time
3024  * Time.gm(year, month, day, hour, min, sec_with_frac) -> time
3025  * Time.gm(year, month, day, hour, min, sec, usec_with_frac) -> time
3026  * Time.gm(sec, min, hour, day, month, year, dummy, dummy, dummy, dummy) -> time
3027  *
3028  * Creates a Time object based on given values, interpreted as UTC (GMT). The
3029  * year must be specified. Other values default to the minimum value
3030  * for that field (and may be +nil+ or omitted). Months may
3031  * be specified by numbers from 1 to 12, or by the three-letter English
3032  * month names. Hours are specified on a 24-hour clock (0..23). Raises
3033  * an ArgumentError if any values are out of range. Will
3034  * also accept ten arguments in the order output by Time#to_a.
3035  *
3036  * +sec_with_frac+ and +usec_with_frac+ can have a fractional part.
3037  *
3038  * Time.utc(2000,"jan",1,20,15,1) #=> 2000-01-01 20:15:01 UTC
3039  * Time.gm(2000,"jan",1,20,15,1) #=> 2000-01-01 20:15:01 UTC
3040  */
3041 static VALUE
3042 time_s_mkutc(int argc, VALUE *argv, VALUE klass)
3043 {
3044  return time_utc_or_local(argc, argv, TRUE, klass);
3045 }
3046 
3047 /*
3048  * call-seq:
3049  * Time.local(year) -> time
3050  * Time.local(year, month) -> time
3051  * Time.local(year, month, day) -> time
3052  * Time.local(year, month, day, hour) -> time
3053  * Time.local(year, month, day, hour, min) -> time
3054  * Time.local(year, month, day, hour, min, sec_with_frac) -> time
3055  * Time.local(year, month, day, hour, min, sec, usec_with_frac) -> time
3056  * Time.local(sec, min, hour, day, month, year, dummy, dummy, isdst, dummy) -> time
3057  * Time.mktime(year) -> time
3058  * Time.mktime(year, month) -> time
3059  * Time.mktime(year, month, day) -> time
3060  * Time.mktime(year, month, day, hour) -> time
3061  * Time.mktime(year, month, day, hour, min) -> time
3062  * Time.mktime(year, month, day, hour, min, sec_with_frac) -> time
3063  * Time.mktime(year, month, day, hour, min, sec, usec_with_frac) -> time
3064  * Time.mktime(sec, min, hour, day, month, year, dummy, dummy, isdst, dummy) -> time
3065  *
3066  * Same as Time::gm, but interprets the values in the
3067  * local time zone.
3068  *
3069  * Time.local(2000,"jan",1,20,15,1) #=> 2000-01-01 20:15:01 -0600
3070  */
3071 
3072 static VALUE
3073 time_s_mktime(int argc, VALUE *argv, VALUE klass)
3074 {
3075  return time_utc_or_local(argc, argv, FALSE, klass);
3076 }
3077 
3078 /*
3079  * call-seq:
3080  * time.to_i -> int
3081  * time.tv_sec -> int
3082  *
3083  * Returns the value of _time_ as an integer number of seconds
3084  * since the Epoch.
3085  *
3086  * t = Time.now
3087  * "%10.5f" % t.to_f #=> "1270968656.89607"
3088  * t.to_i #=> 1270968656
3089  */
3090 
3091 static VALUE
3092 time_to_i(VALUE time)
3093 {
3094  struct time_object *tobj;
3095 
3096  GetTimeval(time, tobj);
3097  return w2v(wdiv(tobj->timew, WINT2FIXWV(TIME_SCALE)));
3098 }
3099 
3100 /*
3101  * call-seq:
3102  * time.to_f -> float
3103  *
3104  * Returns the value of _time_ as a floating point number of
3105  * seconds since the Epoch.
3106  *
3107  * t = Time.now
3108  * "%10.5f" % t.to_f #=> "1270968744.77658"
3109  * t.to_i #=> 1270968744
3110  *
3111  * Note that IEEE 754 double is not accurate enough to represent
3112  * the number of nanoseconds since the Epoch.
3113  */
3114 
3115 static VALUE
3116 time_to_f(VALUE time)
3117 {
3118  struct time_object *tobj;
3119 
3120  GetTimeval(time, tobj);
3121  return rb_Float(rb_time_unmagnify_to_float(tobj->timew));
3122 }
3123 
3124 /*
3125  * call-seq:
3126  * time.to_r -> a_rational
3127  *
3128  * Returns the value of _time_ as a rational number of seconds
3129  * since the Epoch.
3130  *
3131  * t = Time.now
3132  * p t.to_r #=> (1270968792716287611/1000000000)
3133  *
3134  * This methods is intended to be used to get an accurate value
3135  * representing the nanoseconds since the Epoch. You can use this method
3136  * to convert _time_ to another Epoch.
3137  */
3138 
3139 static VALUE
3140 time_to_r(VALUE time)
3141 {
3142  struct time_object *tobj;
3143  VALUE v;
3144 
3145  GetTimeval(time, tobj);
3146  v = w2v(rb_time_unmagnify(tobj->timew));
3147  if (!RB_TYPE_P(v, T_RATIONAL)) {
3148  v = rb_Rational1(v);
3149  }
3150  return v;
3151 }
3152 
3153 /*
3154  * call-seq:
3155  * time.usec -> int
3156  * time.tv_usec -> int
3157  *
3158  * Returns the number of microseconds for _time_.
3159  *
3160  * t = Time.now #=> 2007-11-19 08:03:26 -0600
3161  * "%10.6f" % t.to_f #=> "1195481006.775195"
3162  * t.usec #=> 775195
3163  */
3164 
3165 static VALUE
3166 time_usec(VALUE time)
3167 {
3168  struct time_object *tobj;
3169  wideval_t w, q, r;
3170 
3171  GetTimeval(time, tobj);
3172 
3173  w = wmod(tobj->timew, WINT2WV(TIME_SCALE));
3174  wmuldivmod(w, WINT2FIXWV(1000000), WINT2FIXWV(TIME_SCALE), &q, &r);
3175  return rb_to_int(w2v(q));
3176 }
3177 
3178 /*
3179  * call-seq:
3180  * time.nsec -> int
3181  * time.tv_nsec -> int
3182  *
3183  * Returns the number of nanoseconds for _time_.
3184  *
3185  * t = Time.now #=> 2007-11-17 15:18:03 +0900
3186  * "%10.9f" % t.to_f #=> "1195280283.536151409"
3187  * t.nsec #=> 536151406
3188  *
3189  * The lowest digits of #to_f and #nsec are different because
3190  * IEEE 754 double is not accurate enough to represent
3191  * the exact number of nanoseconds since the Epoch.
3192  *
3193  * The more accurate value is returned by #nsec.
3194  */
3195 
3196 static VALUE
3197 time_nsec(VALUE time)
3198 {
3199  struct time_object *tobj;
3200 
3201  GetTimeval(time, tobj);
3202  return rb_to_int(w2v(wmulquoll(wmod(tobj->timew, WINT2WV(TIME_SCALE)), 1000000000, TIME_SCALE)));
3203 }
3204 
3205 /*
3206  * call-seq:
3207  * time.subsec -> number
3208  *
3209  * Returns the fraction for _time_.
3210  *
3211  * The return value can be a rational number.
3212  *
3213  * t = Time.now #=> 2009-03-26 22:33:12 +0900
3214  * "%10.9f" % t.to_f #=> "1238074392.940563917"
3215  * t.subsec #=> (94056401/100000000)
3216  *
3217  * The lowest digits of #to_f and #subsec are different because
3218  * IEEE 754 double is not accurate enough to represent
3219  * the rational number.
3220  *
3221  * The more accurate value is returned by #subsec.
3222  */
3223 
3224 static VALUE
3225 time_subsec(VALUE time)
3226 {
3227  struct time_object *tobj;
3228 
3229  GetTimeval(time, tobj);
3230  return quov(w2v(wmod(tobj->timew, WINT2FIXWV(TIME_SCALE))), INT2FIX(TIME_SCALE));
3231 }
3232 
3233 /*
3234  * call-seq:
3235  * time <=> other_time -> -1, 0, +1 or nil
3236  *
3237  * Comparison---Compares +time+ with +other_time+.
3238  *
3239  * -1, 0, +1 or nil depending on whether +time+ is less than, equal to, or
3240  * greater than +other_time+.
3241  *
3242  * +nil+ is returned if the two values are incomparable.
3243  *
3244  * t = Time.now #=> 2007-11-19 08:12:12 -0600
3245  * t2 = t + 2592000 #=> 2007-12-19 08:12:12 -0600
3246  * t <=> t2 #=> -1
3247  * t2 <=> t #=> 1
3248  *
3249  * t = Time.now #=> 2007-11-19 08:13:38 -0600
3250  * t2 = t + 0.1 #=> 2007-11-19 08:13:38 -0600
3251  * t.nsec #=> 98222999
3252  * t2.nsec #=> 198222999
3253  * t <=> t2 #=> -1
3254  * t2 <=> t #=> 1
3255  * t <=> t #=> 0
3256  */
3257 
3258 static VALUE
3259 time_cmp(VALUE time1, VALUE time2)
3260 {
3261  struct time_object *tobj1, *tobj2;
3262  int n;
3263 
3264  GetTimeval(time1, tobj1);
3265  if (IsTimeval(time2)) {
3266  GetTimeval(time2, tobj2);
3267  n = wcmp(tobj1->timew, tobj2->timew);
3268  }
3269  else {
3270  return rb_invcmp(time1, time2);
3271  }
3272  if (n == 0) return INT2FIX(0);
3273  if (n > 0) return INT2FIX(1);
3274  return INT2FIX(-1);
3275 }
3276 
3277 /*
3278  * call-seq:
3279  * time.eql?(other_time)
3280  *
3281  * Returns +true+ if _time_ and +other_time+ are
3282  * both Time objects with the same seconds and fractional seconds.
3283  */
3284 
3285 static VALUE
3286 time_eql(VALUE time1, VALUE time2)
3287 {
3288  struct time_object *tobj1, *tobj2;
3289 
3290  GetTimeval(time1, tobj1);
3291  if (IsTimeval(time2)) {
3292  GetTimeval(time2, tobj2);
3293  return rb_equal(w2v(tobj1->timew), w2v(tobj2->timew));
3294  }
3295  return Qfalse;
3296 }
3297 
3298 /*
3299  * call-seq:
3300  * time.utc? -> true or false
3301  * time.gmt? -> true or false
3302  *
3303  * Returns +true+ if _time_ represents a time in UTC (GMT).
3304  *
3305  * t = Time.now #=> 2007-11-19 08:15:23 -0600
3306  * t.utc? #=> false
3307  * t = Time.gm(2000,"jan",1,20,15,1) #=> 2000-01-01 20:15:01 UTC
3308  * t.utc? #=> true
3309  *
3310  * t = Time.now #=> 2007-11-19 08:16:03 -0600
3311  * t.gmt? #=> false
3312  * t = Time.gm(2000,1,1,20,15,1) #=> 2000-01-01 20:15:01 UTC
3313  * t.gmt? #=> true
3314  */
3315 
3316 static VALUE
3317 time_utc_p(VALUE time)
3318 {
3319  struct time_object *tobj;
3320 
3321  GetTimeval(time, tobj);
3322  if (TIME_UTC_P(tobj)) return Qtrue;
3323  return Qfalse;
3324 }
3325 
3326 /*
3327  * call-seq:
3328  * time.hash -> integer
3329  *
3330  * Returns a hash code for this Time object.
3331  *
3332  * See also Object#hash.
3333  */
3334 
3335 static VALUE
3336 time_hash(VALUE time)
3337 {
3338  struct time_object *tobj;
3339 
3340  GetTimeval(time, tobj);
3341  return rb_hash(w2v(tobj->timew));
3342 }
3343 
3344 /* :nodoc: */
3345 static VALUE
3346 time_init_copy(VALUE copy, VALUE time)
3347 {
3348  struct time_object *tobj, *tcopy;
3349 
3350  if (!OBJ_INIT_COPY(copy, time)) return copy;
3351  GetTimeval(time, tobj);
3352  GetNewTimeval(copy, tcopy);
3353  MEMCPY(tcopy, tobj, struct time_object, 1);
3354 
3355  return copy;
3356 }
3357 
3358 static VALUE
3359 time_dup(VALUE time)
3360 {
3361  VALUE dup = time_s_alloc(rb_obj_class(time));
3362  time_init_copy(dup, time);
3363  return dup;
3364 }
3365 
3366 static VALUE
3367 time_localtime(VALUE time)
3368 {
3369  struct time_object *tobj;
3370  struct vtm vtm;
3371 
3372  GetTimeval(time, tobj);
3373  if (TIME_LOCALTIME_P(tobj)) {
3374  if (tobj->tm_got)
3375  return time;
3376  }
3377  else {
3378  time_modify(time);
3379  }
3380 
3381  if (!localtimew(tobj->timew, &vtm))
3382  rb_raise(rb_eArgError, "localtime error");
3383  tobj->vtm = vtm;
3384 
3385  tobj->tm_got = 1;
3386  TIME_SET_LOCALTIME(tobj);
3387  return time;
3388 }
3389 
3390 /*
3391  * call-seq:
3392  * time.localtime -> time
3393  * time.localtime(utc_offset) -> time
3394  *
3395  * Converts _time_ to local time (using the local time zone in
3396  * effect for this process) modifying the receiver.
3397  *
3398  * If +utc_offset+ is given, it is used instead of the local time.
3399  *
3400  * t = Time.utc(2000, "jan", 1, 20, 15, 1) #=> 2000-01-01 20:15:01 UTC
3401  * t.utc? #=> true
3402  *
3403  * t.localtime #=> 2000-01-01 14:15:01 -0600
3404  * t.utc? #=> false
3405  *
3406  * t.localtime("+09:00") #=> 2000-01-02 05:15:01 +0900
3407  * t.utc? #=> false
3408  */
3409 
3410 static VALUE
3411 time_localtime_m(int argc, VALUE *argv, VALUE time)
3412 {
3413  VALUE off;
3414  rb_scan_args(argc, argv, "01", &off);
3415 
3416  if (!NIL_P(off)) {
3417  off = utc_offset_arg(off);
3418  validate_utc_offset(off);
3419 
3420  time_set_utc_offset(time, off);
3421  return time_fixoff(time);
3422  }
3423 
3424  return time_localtime(time);
3425 }
3426 
3427 /*
3428  * call-seq:
3429  * time.gmtime -> time
3430  * time.utc -> time
3431  *
3432  * Converts _time_ to UTC (GMT), modifying the receiver.
3433  *
3434  * t = Time.now #=> 2007-11-19 08:18:31 -0600
3435  * t.gmt? #=> false
3436  * t.gmtime #=> 2007-11-19 14:18:31 UTC
3437  * t.gmt? #=> true
3438  *
3439  * t = Time.now #=> 2007-11-19 08:18:51 -0600
3440  * t.utc? #=> false
3441  * t.utc #=> 2007-11-19 14:18:51 UTC
3442  * t.utc? #=> true
3443  */
3444 
3445 static VALUE
3446 time_gmtime(VALUE time)
3447 {
3448  struct time_object *tobj;
3449  struct vtm vtm;
3450 
3451  GetTimeval(time, tobj);
3452  if (TIME_UTC_P(tobj)) {
3453  if (tobj->tm_got)
3454  return time;
3455  }
3456  else {
3457  time_modify(time);
3458  }
3459 
3460  if (!gmtimew(tobj->timew, &vtm))
3461  rb_raise(rb_eArgError, "gmtime error");
3462  tobj->vtm = vtm;
3463 
3464  tobj->tm_got = 1;
3465  TIME_SET_UTC(tobj);
3466  return time;
3467 }
3468 
3469 static VALUE
3470 time_fixoff(VALUE time)
3471 {
3472  struct time_object *tobj;
3473  struct vtm vtm;
3474  VALUE off;
3475 
3476  GetTimeval(time, tobj);
3477  if (TIME_FIXOFF_P(tobj)) {
3478  if (tobj->tm_got)
3479  return time;
3480  }
3481  else {
3482  time_modify(time);
3483  }
3484 
3485  if (TIME_FIXOFF_P(tobj))
3486  off = tobj->vtm.utc_offset;
3487  else
3488  off = INT2FIX(0);
3489 
3490  if (!gmtimew(tobj->timew, &vtm))
3491  rb_raise(rb_eArgError, "gmtime error");
3492 
3493  tobj->vtm = vtm;
3494  vtm_add_offset(&tobj->vtm, off);
3495 
3496  tobj->tm_got = 1;
3497  TIME_SET_FIXOFF(tobj, off);
3498  return time;
3499 }
3500 
3501 /*
3502  * call-seq:
3503  * time.getlocal -> new_time
3504  * time.getlocal(utc_offset) -> new_time
3505  *
3506  * Returns a new Time object representing _time_ in
3507  * local time (using the local time zone in effect for this process).
3508  *
3509  * If +utc_offset+ is given, it is used instead of the local time.
3510  * +utc_offset+ can be given as a human-readable string (eg. <code>"+09:00"</code>)
3511  * or as a number of seconds (eg. <code>32400</code>).
3512  *
3513  * t = Time.utc(2000,1,1,20,15,1) #=> 2000-01-01 20:15:01 UTC
3514  * t.utc? #=> true
3515  *
3516  * l = t.getlocal #=> 2000-01-01 14:15:01 -0600
3517  * l.utc? #=> false
3518  * t == l #=> true
3519  *
3520  * j = t.getlocal("+09:00") #=> 2000-01-02 05:15:01 +0900
3521  * j.utc? #=> false
3522  * t == j #=> true
3523  *
3524  * k = t.getlocal(9*60*60) #=> 2000-01-02 05:15:01 +0900
3525  * k.utc? #=> false
3526  * t == k #=> true
3527  */
3528 
3529 static VALUE
3530 time_getlocaltime(int argc, VALUE *argv, VALUE time)
3531 {
3532  VALUE off;
3533  rb_scan_args(argc, argv, "01", &off);
3534 
3535  if (!NIL_P(off)) {
3536  off = utc_offset_arg(off);
3537  validate_utc_offset(off);
3538 
3539  time = time_dup(time);
3540  time_set_utc_offset(time, off);
3541  return time_fixoff(time);
3542  }
3543 
3544  return time_localtime(time_dup(time));
3545 }
3546 
3547 /*
3548  * call-seq:
3549  * time.getgm -> new_time
3550  * time.getutc -> new_time
3551  *
3552  * Returns a new Time object representing _time_ in UTC.
3553  *
3554  * t = Time.local(2000,1,1,20,15,1) #=> 2000-01-01 20:15:01 -0600
3555  * t.gmt? #=> false
3556  * y = t.getgm #=> 2000-01-02 02:15:01 UTC
3557  * y.gmt? #=> true
3558  * t == y #=> true
3559  */
3560 
3561 static VALUE
3562 time_getgmtime(VALUE time)
3563 {
3564  return time_gmtime(time_dup(time));
3565 }
3566 
3567 static VALUE
3568 time_get_tm(VALUE time, struct time_object *tobj)
3569 {
3570  if (TIME_UTC_P(tobj)) return time_gmtime(time);
3571  if (TIME_FIXOFF_P(tobj)) return time_fixoff(time);
3572  return time_localtime(time);
3573 }
3574 
3575 static VALUE strftime_cstr(const char *fmt, size_t len, VALUE time, rb_encoding *enc);
3576 #define strftimev(fmt, time, enc) strftime_cstr((fmt), rb_strlen_lit(fmt), (time), (enc))
3577 
3578 /*
3579  * call-seq:
3580  * time.asctime -> string
3581  * time.ctime -> string
3582  *
3583  * Returns a canonical string representation of _time_.
3584  *
3585  * Time.now.asctime #=> "Wed Apr 9 08:56:03 2003"
3586  * Time.now.ctime #=> "Wed Apr 9 08:56:03 2003"
3587  */
3588 
3589 static VALUE
3590 time_asctime(VALUE time)
3591 {
3592  return strftimev("%a %b %e %T %Y", time, rb_usascii_encoding());
3593 }
3594 
3595 /*
3596  * call-seq:
3597  * time.inspect -> string
3598  * time.to_s -> string
3599  *
3600  * Returns a string representing _time_. Equivalent to calling
3601  * #strftime with the appropriate format string.
3602  *
3603  * t = Time.now
3604  * t.to_s => "2012-11-10 18:16:12 +0100"
3605  * t.strftime "%Y-%m-%d %H:%M:%S %z" => "2012-11-10 18:16:12 +0100"
3606  *
3607  * t.utc.to_s => "2012-11-10 17:16:12 UTC"
3608  * t.strftime "%Y-%m-%d %H:%M:%S UTC" => "2012-11-10 17:16:12 UTC"
3609  */
3610 
3611 static VALUE
3612 time_to_s(VALUE time)
3613 {
3614  struct time_object *tobj;
3615 
3616  GetTimeval(time, tobj);
3617  if (TIME_UTC_P(tobj))
3618  return strftimev("%Y-%m-%d %H:%M:%S UTC", time, rb_usascii_encoding());
3619  else
3620  return strftimev("%Y-%m-%d %H:%M:%S %z", time, rb_usascii_encoding());
3621 }
3622 
3623 static VALUE
3624 time_add(struct time_object *tobj, VALUE torig, VALUE offset, int sign)
3625 {
3626  VALUE result, zone;
3627  offset = num_exact(offset);
3628  if (sign < 0)
3629  result = time_new_timew(rb_cTime, wsub(tobj->timew, rb_time_magnify(v2w(offset))));
3630  else
3631  result = time_new_timew(rb_cTime, wadd(tobj->timew, rb_time_magnify(v2w(offset))));
3632  if (TIME_UTC_P(tobj)) {
3633  GetTimeval(result, tobj);
3634  TIME_SET_UTC(tobj);
3635  }
3636  else if (TIME_FIXOFF_P(tobj)) {
3637  VALUE off = tobj->vtm.utc_offset;
3638  GetTimeval(result, tobj);
3639  TIME_SET_FIXOFF(tobj, off);
3640  }
3641  if (!tobj->vtm.zone && !NIL_P(zone = rb_attr_get(torig, id_zone))) {
3642  tobj->vtm.zone = StringValueCStr(zone);
3643  rb_ivar_set(result, id_zone, zone);
3644  }
3645 
3646  return result;
3647 }
3648 
3649 /*
3650  * call-seq:
3651  * time + numeric -> time
3652  *
3653  * Addition --- Adds some number of seconds (possibly fractional) to
3654  * _time_ and returns that value as a new Time object.
3655  *
3656  * t = Time.now #=> 2007-11-19 08:22:21 -0600
3657  * t + (60 * 60 * 24) #=> 2007-11-20 08:22:21 -0600
3658  */
3659 
3660 static VALUE
3661 time_plus(VALUE time1, VALUE time2)
3662 {
3663  struct time_object *tobj;
3664  GetTimeval(time1, tobj);
3665 
3666  if (IsTimeval(time2)) {
3667  rb_raise(rb_eTypeError, "time + time?");
3668  }
3669  return time_add(tobj, time1, time2, 1);
3670 }
3671 
3672 /*
3673  * call-seq:
3674  * time - other_time -> float
3675  * time - numeric -> time
3676  *
3677  * Difference --- Returns a difference in seconds as a Float
3678  * between _time_ and +other_time+, or subtracts the given number
3679  * of seconds in +numeric+ from _time_.
3680  *
3681  * t = Time.now #=> 2007-11-19 08:23:10 -0600
3682  * t2 = t + 2592000 #=> 2007-12-19 08:23:10 -0600
3683  * t2 - t #=> 2592000.0
3684  * t2 - 2592000 #=> 2007-11-19 08:23:10 -0600
3685  */
3686 
3687 static VALUE
3688 time_minus(VALUE time1, VALUE time2)
3689 {
3690  struct time_object *tobj;
3691 
3692  GetTimeval(time1, tobj);
3693  if (IsTimeval(time2)) {
3694  struct time_object *tobj2;
3695 
3696  GetTimeval(time2, tobj2);
3697  return rb_Float(rb_time_unmagnify_to_float(wsub(tobj->timew, tobj2->timew)));
3698  }
3699  return time_add(tobj, time1, time2, -1);
3700 }
3701 
3702 /*
3703  * call-seq:
3704  * time.succ -> new_time
3705  *
3706  * Returns a new Time object, one second later than _time_.
3707  * Time#succ is obsolete since 1.9.2 for time is not a discrete value.
3708  *
3709  * t = Time.now #=> 2007-11-19 08:23:57 -0600
3710  * t.succ #=> 2007-11-19 08:23:58 -0600
3711  *
3712  * Use instead <code>time + 1</code>
3713  *
3714  * t + 1 #=> 2007-11-19 08:23:58 -0600
3715  */
3716 
3717 VALUE
3718 rb_time_succ(VALUE time)
3719 {
3720  struct time_object *tobj;
3721  struct time_object *tobj2;
3722 
3723  rb_warn("Time#succ is obsolete; use time + 1");
3724  GetTimeval(time, tobj);
3725  time = time_new_timew(rb_cTime, wadd(tobj->timew, WINT2FIXWV(TIME_SCALE)));
3726  GetTimeval(time, tobj2);
3727  TIME_COPY_GMT(tobj2, tobj);
3728  return time;
3729 }
3730 
3731 #define time_succ rb_time_succ
3732 
3733 /*
3734  * call-seq:
3735  * time.round([ndigits]) -> new_time
3736  *
3737  * Rounds sub seconds to a given precision in decimal digits (0 digits by default).
3738  * It returns a new Time object.
3739  * +ndigits+ should be zero or positive integer.
3740  *
3741  * require 'time'
3742  *
3743  * t = Time.utc(2010,3,30, 5,43,"25.123456789".to_r)
3744  * p t.iso8601(10) #=> "2010-03-30T05:43:25.1234567890Z"
3745  * p t.round.iso8601(10) #=> "2010-03-30T05:43:25.0000000000Z"
3746  * p t.round(0).iso8601(10) #=> "2010-03-30T05:43:25.0000000000Z"
3747  * p t.round(1).iso8601(10) #=> "2010-03-30T05:43:25.1000000000Z"
3748  * p t.round(2).iso8601(10) #=> "2010-03-30T05:43:25.1200000000Z"
3749  * p t.round(3).iso8601(10) #=> "2010-03-30T05:43:25.1230000000Z"
3750  * p t.round(4).iso8601(10) #=> "2010-03-30T05:43:25.1235000000Z"
3751  * p t.round(5).iso8601(10) #=> "2010-03-30T05:43:25.1234600000Z"
3752  * p t.round(6).iso8601(10) #=> "2010-03-30T05:43:25.1234570000Z"
3753  * p t.round(7).iso8601(10) #=> "2010-03-30T05:43:25.1234568000Z"
3754  * p t.round(8).iso8601(10) #=> "2010-03-30T05:43:25.1234567900Z"
3755  * p t.round(9).iso8601(10) #=> "2010-03-30T05:43:25.1234567890Z"
3756  * p t.round(10).iso8601(10) #=> "2010-03-30T05:43:25.1234567890Z"
3757  *
3758  * t = Time.utc(1999,12,31, 23,59,59)
3759  * p((t + 0.4).round.iso8601(3)) #=> "1999-12-31T23:59:59.000Z"
3760  * p((t + 0.49).round.iso8601(3)) #=> "1999-12-31T23:59:59.000Z"
3761  * p((t + 0.5).round.iso8601(3)) #=> "2000-01-01T00:00:00.000Z"
3762  * p((t + 1.4).round.iso8601(3)) #=> "2000-01-01T00:00:00.000Z"
3763  * p((t + 1.49).round.iso8601(3)) #=> "2000-01-01T00:00:00.000Z"
3764  * p((t + 1.5).round.iso8601(3)) #=> "2000-01-01T00:00:01.000Z"
3765  *
3766  * t = Time.utc(1999,12,31, 23,59,59)
3767  * p (t + 0.123456789).round(4).iso8601(6) #=> "1999-12-31T23:59:59.123500Z"
3768  */
3769 
3770 static VALUE
3771 time_round(int argc, VALUE *argv, VALUE time)
3772 {
3773  VALUE ndigits, v, a, b, den;
3774  long nd;
3775  struct time_object *tobj;
3776 
3777  rb_scan_args(argc, argv, "01", &ndigits);
3778 
3779  if (NIL_P(ndigits))
3780  ndigits = INT2FIX(0);
3781  else
3782  ndigits = rb_to_int(ndigits);
3783 
3784  nd = NUM2LONG(ndigits);
3785  if (nd < 0)
3786  rb_raise(rb_eArgError, "negative ndigits given");
3787 
3788  GetTimeval(time, tobj);
3789  v = w2v(rb_time_unmagnify(tobj->timew));
3790 
3791  a = INT2FIX(1);
3792  b = INT2FIX(10);
3793  while (0 < nd) {
3794  if (nd & 1)
3795  a = mulv(a, b);
3796  b = mulv(b, b);
3797  nd = nd >> 1;
3798  }
3799  den = quov(INT2FIX(1), a);
3800  v = modv(v, den);
3801  if (lt(v, quov(den, INT2FIX(2))))
3802  return time_add(tobj, time, v, -1);
3803  else
3804  return time_add(tobj, time, subv(den, v), 1);
3805 }
3806 
3807 /*
3808  * call-seq:
3809  * time.sec -> integer
3810  *
3811  * Returns the second of the minute (0..60) for _time_.
3812  *
3813  * *Note:* Seconds range from zero to 60 to allow the system to inject
3814  * leap seconds. See http://en.wikipedia.org/wiki/Leap_second for further
3815  * details.
3816  *
3817  * t = Time.now #=> 2007-11-19 08:25:02 -0600
3818  * t.sec #=> 2
3819  */
3820 
3821 static VALUE
3822 time_sec(VALUE time)
3823 {
3824  struct time_object *tobj;
3825 
3826  GetTimeval(time, tobj);
3827  MAKE_TM(time, tobj);
3828  return INT2FIX(tobj->vtm.sec);
3829 }
3830 
3831 /*
3832  * call-seq:
3833  * time.min -> integer
3834  *
3835  * Returns the minute of the hour (0..59) for _time_.
3836  *
3837  * t = Time.now #=> 2007-11-19 08:25:51 -0600
3838  * t.min #=> 25
3839  */
3840 
3841 static VALUE
3842 time_min(VALUE time)
3843 {
3844  struct time_object *tobj;
3845 
3846  GetTimeval(time, tobj);
3847  MAKE_TM(time, tobj);
3848  return INT2FIX(tobj->vtm.min);
3849 }
3850 
3851 /*
3852  * call-seq:
3853  * time.hour -> integer
3854  *
3855  * Returns the hour of the day (0..23) for _time_.
3856  *
3857  * t = Time.now #=> 2007-11-19 08:26:20 -0600
3858  * t.hour #=> 8
3859  */
3860 
3861 static VALUE
3862 time_hour(VALUE time)
3863 {
3864  struct time_object *tobj;
3865 
3866  GetTimeval(time, tobj);
3867  MAKE_TM(time, tobj);
3868  return INT2FIX(tobj->vtm.hour);
3869 }
3870 
3871 /*
3872  * call-seq:
3873  * time.day -> integer
3874  * time.mday -> integer
3875  *
3876  * Returns the day of the month (1..n) for _time_.
3877  *
3878  * t = Time.now #=> 2007-11-19 08:27:03 -0600
3879  * t.day #=> 19
3880  * t.mday #=> 19
3881  */
3882 
3883 static VALUE
3884 time_mday(VALUE time)
3885 {
3886  struct time_object *tobj;
3887 
3888  GetTimeval(time, tobj);
3889  MAKE_TM(time, tobj);
3890  return INT2FIX(tobj->vtm.mday);
3891 }
3892 
3893 /*
3894  * call-seq:
3895  * time.mon -> integer
3896  * time.month -> integer
3897  *
3898  * Returns the month of the year (1..12) for _time_.
3899  *
3900  * t = Time.now #=> 2007-11-19 08:27:30 -0600
3901  * t.mon #=> 11
3902  * t.month #=> 11
3903  */
3904 
3905 static VALUE
3906 time_mon(VALUE time)
3907 {
3908  struct time_object *tobj;
3909 
3910  GetTimeval(time, tobj);
3911  MAKE_TM(time, tobj);
3912  return INT2FIX(tobj->vtm.mon);
3913 }
3914 
3915 /*
3916  * call-seq:
3917  * time.year -> integer
3918  *
3919  * Returns the year for _time_ (including the century).
3920  *
3921  * t = Time.now #=> 2007-11-19 08:27:51 -0600
3922  * t.year #=> 2007
3923  */
3924 
3925 static VALUE
3926 time_year(VALUE time)
3927 {
3928  struct time_object *tobj;
3929 
3930  GetTimeval(time, tobj);
3931  MAKE_TM(time, tobj);
3932  return tobj->vtm.year;
3933 }
3934 
3935 /*
3936  * call-seq:
3937  * time.wday -> integer
3938  *
3939  * Returns an integer representing the day of the week, 0..6, with
3940  * Sunday == 0.
3941  *
3942  * t = Time.now #=> 2007-11-20 02:35:35 -0600
3943  * t.wday #=> 2
3944  * t.sunday? #=> false
3945  * t.monday? #=> false
3946  * t.tuesday? #=> true
3947  * t.wednesday? #=> false
3948  * t.thursday? #=> false
3949  * t.friday? #=> false
3950  * t.saturday? #=> false
3951  */
3952 
3953 static VALUE
3954 time_wday(VALUE time)
3955 {
3956  struct time_object *tobj;
3957 
3958  GetTimeval(time, tobj);
3959  MAKE_TM(time, tobj);
3960  return INT2FIX((int)tobj->vtm.wday);
3961 }
3962 
3963 #define wday_p(n) {\
3964  struct time_object *tobj;\
3965  GetTimeval(time, tobj);\
3966  MAKE_TM(time, tobj);\
3967  return (tobj->vtm.wday == (n)) ? Qtrue : Qfalse;\
3968 }
3969 
3970 /*
3971  * call-seq:
3972  * time.sunday? -> true or false
3973  *
3974  * Returns +true+ if _time_ represents Sunday.
3975  *
3976  * t = Time.local(1990, 4, 1) #=> 1990-04-01 00:00:00 -0600
3977  * t.sunday? #=> true
3978  */
3979 
3980 static VALUE
3981 time_sunday(VALUE time)
3982 {
3983  wday_p(0);
3984 }
3985 
3986 /*
3987  * call-seq:
3988  * time.monday? -> true or false
3989  *
3990  * Returns +true+ if _time_ represents Monday.
3991  *
3992  * t = Time.local(2003, 8, 4) #=> 2003-08-04 00:00:00 -0500
3993  * p t.monday? #=> true
3994  */
3995 
3996 static VALUE
3997 time_monday(VALUE time)
3998 {
3999  wday_p(1);
4000 }
4001 
4002 /*
4003  * call-seq:
4004  * time.tuesday? -> true or false
4005  *
4006  * Returns +true+ if _time_ represents Tuesday.
4007  *
4008  * t = Time.local(1991, 2, 19) #=> 1991-02-19 00:00:00 -0600
4009  * p t.tuesday? #=> true
4010  */
4011 
4012 static VALUE
4013 time_tuesday(VALUE time)
4014 {
4015  wday_p(2);
4016 }
4017 
4018 /*
4019  * call-seq:
4020  * time.wednesday? -> true or false
4021  *
4022  * Returns +true+ if _time_ represents Wednesday.
4023  *
4024  * t = Time.local(1993, 2, 24) #=> 1993-02-24 00:00:00 -0600
4025  * p t.wednesday? #=> true
4026  */
4027 
4028 static VALUE
4029 time_wednesday(VALUE time)
4030 {
4031  wday_p(3);
4032 }
4033 
4034 /*
4035  * call-seq:
4036  * time.thursday? -> true or false
4037  *
4038  * Returns +true+ if _time_ represents Thursday.
4039  *
4040  * t = Time.local(1995, 12, 21) #=> 1995-12-21 00:00:00 -0600
4041  * p t.thursday? #=> true
4042  */
4043 
4044 static VALUE
4045 time_thursday(VALUE time)
4046 {
4047  wday_p(4);
4048 }
4049 
4050 /*
4051  * call-seq:
4052  * time.friday? -> true or false
4053  *
4054  * Returns +true+ if _time_ represents Friday.
4055  *
4056  * t = Time.local(1987, 12, 18) #=> 1987-12-18 00:00:00 -0600
4057  * t.friday? #=> true
4058  */
4059 
4060 static VALUE
4061 time_friday(VALUE time)
4062 {
4063  wday_p(5);
4064 }
4065 
4066 /*
4067  * call-seq:
4068  * time.saturday? -> true or false
4069  *
4070  * Returns +true+ if _time_ represents Saturday.
4071  *
4072  * t = Time.local(2006, 6, 10) #=> 2006-06-10 00:00:00 -0500
4073  * t.saturday? #=> true
4074  */
4075 
4076 static VALUE
4077 time_saturday(VALUE time)
4078 {
4079  wday_p(6);
4080 }
4081 
4082 /*
4083  * call-seq:
4084  * time.yday -> integer
4085  *
4086  * Returns an integer representing the day of the year, 1..366.
4087  *
4088  * t = Time.now #=> 2007-11-19 08:32:31 -0600
4089  * t.yday #=> 323
4090  */
4091 
4092 static VALUE
4093 time_yday(VALUE time)
4094 {
4095  struct time_object *tobj;
4096 
4097  GetTimeval(time, tobj);
4098  MAKE_TM(time, tobj);
4099  return INT2FIX(tobj->vtm.yday);
4100 }
4101 
4102 /*
4103  * call-seq:
4104  * time.isdst -> true or false
4105  * time.dst? -> true or false
4106  *
4107  * Returns +true+ if _time_ occurs during Daylight
4108  * Saving Time in its time zone.
4109  *
4110  * # CST6CDT:
4111  * Time.local(2000, 1, 1).zone #=> "CST"
4112  * Time.local(2000, 1, 1).isdst #=> false
4113  * Time.local(2000, 1, 1).dst? #=> false
4114  * Time.local(2000, 7, 1).zone #=> "CDT"
4115  * Time.local(2000, 7, 1).isdst #=> true
4116  * Time.local(2000, 7, 1).dst? #=> true
4117  *
4118  * # Asia/Tokyo:
4119  * Time.local(2000, 1, 1).zone #=> "JST"
4120  * Time.local(2000, 1, 1).isdst #=> false
4121  * Time.local(2000, 1, 1).dst? #=> false
4122  * Time.local(2000, 7, 1).zone #=> "JST"
4123  * Time.local(2000, 7, 1).isdst #=> false
4124  * Time.local(2000, 7, 1).dst? #=> false
4125  */
4126 
4127 static VALUE
4128 time_isdst(VALUE time)
4129 {
4130  struct time_object *tobj;
4131 
4132  GetTimeval(time, tobj);
4133  MAKE_TM(time, tobj);
4134  return tobj->vtm.isdst ? Qtrue : Qfalse;
4135 }
4136 
4137 static VALUE
4138 time_zone_name(const char *zone)
4139 {
4140  VALUE name = rb_str_new_cstr(zone);
4141  if (!rb_enc_str_asciionly_p(name)) {
4143  }
4144  else {
4146  }
4147  return name;
4148 }
4149 
4150 /*
4151  * call-seq:
4152  * time.zone -> string
4153  *
4154  * Returns the name of the time zone used for _time_. As of Ruby
4155  * 1.8, returns ``UTC'' rather than ``GMT'' for UTC times.
4156  *
4157  * t = Time.gm(2000, "jan", 1, 20, 15, 1)
4158  * t.zone #=> "UTC"
4159  * t = Time.local(2000, "jan", 1, 20, 15, 1)
4160  * t.zone #=> "CST"
4161  */
4162 
4163 static VALUE
4164 time_zone(VALUE time)
4165 {
4166  struct time_object *tobj;
4167 
4168  GetTimeval(time, tobj);
4169  MAKE_TM(time, tobj);
4170 
4171  if (TIME_UTC_P(tobj)) {
4172  return rb_usascii_str_new_cstr("UTC");
4173  }
4174  if (tobj->vtm.zone == NULL)
4175  return Qnil;
4176 
4177  return time_zone_name(tobj->vtm.zone);
4178 }
4179 
4180 /*
4181  * call-seq:
4182  * time.gmt_offset -> integer
4183  * time.gmtoff -> integer
4184  * time.utc_offset -> integer
4185  *
4186  * Returns the offset in seconds between the timezone of _time_
4187  * and UTC.
4188  *
4189  * t = Time.gm(2000,1,1,20,15,1) #=> 2000-01-01 20:15:01 UTC
4190  * t.gmt_offset #=> 0
4191  * l = t.getlocal #=> 2000-01-01 14:15:01 -0600
4192  * l.gmt_offset #=> -21600
4193  */
4194 
4195 static VALUE
4196 time_utc_offset(VALUE time)
4197 {
4198  struct time_object *tobj;
4199 
4200  GetTimeval(time, tobj);
4201  MAKE_TM(time, tobj);
4202 
4203  if (TIME_UTC_P(tobj)) {
4204  return INT2FIX(0);
4205  }
4206  else {
4207  return tobj->vtm.utc_offset;
4208  }
4209 }
4210 
4211 /*
4212  * call-seq:
4213  * time.to_a -> array
4214  *
4215  * Returns a ten-element _array_ of values for _time_:
4216  *
4217  * [sec, min, hour, day, month, year, wday, yday, isdst, zone]
4218  *
4219  * See the individual methods for an explanation of the
4220  * valid ranges of each value. The ten elements can be passed directly
4221  * to Time::utc or Time::local to create a
4222  * new Time object.
4223  *
4224  * t = Time.now #=> 2007-11-19 08:36:01 -0600
4225  * now = t.to_a #=> [1, 36, 8, 19, 11, 2007, 1, 323, false, "CST"]
4226  */
4227 
4228 static VALUE
4229 time_to_a(VALUE time)
4230 {
4231  struct time_object *tobj;
4232 
4233  GetTimeval(time, tobj);
4234  MAKE_TM(time, tobj);
4235  return rb_ary_new3(10,
4236  INT2FIX(tobj->vtm.sec),
4237  INT2FIX(tobj->vtm.min),
4238  INT2FIX(tobj->vtm.hour),
4239  INT2FIX(tobj->vtm.mday),
4240  INT2FIX(tobj->vtm.mon),
4241  tobj->vtm.year,
4242  INT2FIX(tobj->vtm.wday),
4243  INT2FIX(tobj->vtm.yday),
4244  tobj->vtm.isdst?Qtrue:Qfalse,
4245  time_zone(time));
4246 }
4247 
4248 static VALUE
4249 rb_strftime_alloc(const char *format, size_t format_len, rb_encoding *enc,
4250  struct vtm *vtm, wideval_t timew, int gmt)
4251 {
4252  VALUE timev = Qnil;
4253  struct timespec ts;
4254 
4255  if (!timew2timespec_exact(timew, &ts))
4256  timev = w2v(rb_time_unmagnify(timew));
4257 
4258  if (NIL_P(timev)) {
4259  return rb_strftime_timespec(format, format_len, enc, vtm, &ts, gmt);
4260  }
4261  else {
4262  return rb_strftime(format, format_len, enc, vtm, timev, gmt);
4263  }
4264 }
4265 
4266 static VALUE
4267 strftime_cstr(const char *fmt, size_t len, VALUE time, rb_encoding *enc)
4268 {
4269  struct time_object *tobj;
4270  VALUE str;
4271 
4272  GetTimeval(time, tobj);
4273  MAKE_TM(time, tobj);
4274  str = rb_strftime_alloc(fmt, len, enc, &tobj->vtm, tobj->timew, TIME_UTC_P(tobj));
4275  if (!str) rb_raise(rb_eArgError, "invalid format: %s", fmt);
4276  return str;
4277 }
4278 
4279 /*
4280  * call-seq:
4281  * time.strftime( string ) -> string
4282  *
4283  * Formats _time_ according to the directives in the given format string.
4284  *
4285  * The directives begin with a percent (%) character.
4286  * Any text not listed as a directive will be passed through to the
4287  * output string.
4288  *
4289  * The directive consists of a percent (%) character,
4290  * zero or more flags, optional minimum field width,
4291  * optional modifier and a conversion specifier
4292  * as follows:
4293  *
4294  * %<flags><width><modifier><conversion>
4295  *
4296  * Flags:
4297  * - don't pad a numerical output
4298  * _ use spaces for padding
4299  * 0 use zeros for padding
4300  * ^ upcase the result string
4301  * # change case
4302  * : use colons for %z
4303  *
4304  * The minimum field width specifies the minimum width.
4305  *
4306  * The modifiers are "E" and "O".
4307  * They are ignored.
4308  *
4309  * Format directives:
4310  *
4311  * Date (Year, Month, Day):
4312  * %Y - Year with century if provided, will pad result at least 4 digits.
4313  * -0001, 0000, 1995, 2009, 14292, etc.
4314  * %C - year / 100 (rounded down such as 20 in 2009)
4315  * %y - year % 100 (00..99)
4316  *
4317  * %m - Month of the year, zero-padded (01..12)
4318  * %_m blank-padded ( 1..12)
4319  * %-m no-padded (1..12)
4320  * %B - The full month name (``January'')
4321  * %^B uppercased (``JANUARY'')
4322  * %b - The abbreviated month name (``Jan'')
4323  * %^b uppercased (``JAN'')
4324  * %h - Equivalent to %b
4325  *
4326  * %d - Day of the month, zero-padded (01..31)
4327  * %-d no-padded (1..31)
4328  * %e - Day of the month, blank-padded ( 1..31)
4329  *
4330  * %j - Day of the year (001..366)
4331  *
4332  * Time (Hour, Minute, Second, Subsecond):
4333  * %H - Hour of the day, 24-hour clock, zero-padded (00..23)
4334  * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
4335  * %I - Hour of the day, 12-hour clock, zero-padded (01..12)
4336  * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12)
4337  * %P - Meridian indicator, lowercase (``am'' or ``pm'')
4338  * %p - Meridian indicator, uppercase (``AM'' or ``PM'')
4339  *
4340  * %M - Minute of the hour (00..59)
4341  *
4342  * %S - Second of the minute (00..60)
4343  *
4344  * %L - Millisecond of the second (000..999)
4345  * The digits under millisecond are truncated to not produce 1000.
4346  * %N - Fractional seconds digits, default is 9 digits (nanosecond)
4347  * %3N millisecond (3 digits)
4348  * %6N microsecond (6 digits)
4349  * %9N nanosecond (9 digits)
4350  * %12N picosecond (12 digits)
4351  * %15N femtosecond (15 digits)
4352  * %18N attosecond (18 digits)
4353  * %21N zeptosecond (21 digits)
4354  * %24N yoctosecond (24 digits)
4355  * The digits under the specified length are truncated to avoid
4356  * carry up.
4357  *
4358  * Time zone:
4359  * %z - Time zone as hour and minute offset from UTC (e.g. +0900)
4360  * %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
4361  * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
4362  * %Z - Abbreviated time zone name or similar information. (OS dependent)
4363  *
4364  * Weekday:
4365  * %A - The full weekday name (``Sunday'')
4366  * %^A uppercased (``SUNDAY'')
4367  * %a - The abbreviated name (``Sun'')
4368  * %^a uppercased (``SUN'')
4369  * %u - Day of the week (Monday is 1, 1..7)
4370  * %w - Day of the week (Sunday is 0, 0..6)
4371  *
4372  * ISO 8601 week-based year and week number:
4373  * The first week of YYYY starts with a Monday and includes YYYY-01-04.
4374  * The days in the year before the first week are in the last week of
4375  * the previous year.
4376  * %G - The week-based year
4377  * %g - The last 2 digits of the week-based year (00..99)
4378  * %V - Week number of the week-based year (01..53)
4379  *
4380  * Week number:
4381  * The first week of YYYY that starts with a Sunday or Monday (according to %U
4382  * or %W). The days in the year before the first week are in week 0.
4383  * %U - Week number of the year. The week starts with Sunday. (00..53)
4384  * %W - Week number of the year. The week starts with Monday. (00..53)
4385  *
4386  * Seconds since the Epoch:
4387  * %s - Number of seconds since 1970-01-01 00:00:00 UTC.
4388  *
4389  * Literal string:
4390  * %n - Newline character (\n)
4391  * %t - Tab character (\t)
4392  * %% - Literal ``%'' character
4393  *
4394  * Combination:
4395  * %c - date and time (%a %b %e %T %Y)
4396  * %D - Date (%m/%d/%y)
4397  * %F - The ISO 8601 date format (%Y-%m-%d)
4398  * %v - VMS date (%e-%^b-%4Y)
4399  * %x - Same as %D
4400  * %X - Same as %T
4401  * %r - 12-hour time (%I:%M:%S %p)
4402  * %R - 24-hour time (%H:%M)
4403  * %T - 24-hour time (%H:%M:%S)
4404  *
4405  * This method is similar to strftime() function defined in ISO C and POSIX.
4406  *
4407  * While all directives are locale independent since Ruby 1.9, %Z is platform
4408  * dependent.
4409  * So, the result may differ even if the same format string is used in other
4410  * systems such as C.
4411  *
4412  * %z is recommended over %Z.
4413  * %Z doesn't identify the timezone.
4414  * For example, "CST" is used at America/Chicago (-06:00),
4415  * America/Havana (-05:00), Asia/Harbin (+08:00), Australia/Darwin (+09:30)
4416  * and Australia/Adelaide (+10:30).
4417  * Also, %Z is highly dependent on the operating system.
4418  * For example, it may generate a non ASCII string on Japanese Windows.
4419  * i.e. the result can be different to "JST".
4420  * So the numeric time zone offset, %z, is recommended.
4421  *
4422  * Examples:
4423  *
4424  * t = Time.new(2007,11,19,8,37,48,"-06:00") #=> 2007-11-19 08:37:48 -0600
4425  * t.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007"
4426  * t.strftime("at %I:%M%p") #=> "at 08:37AM"
4427  *
4428  * Various ISO 8601 formats:
4429  * %Y%m%d => 20071119 Calendar date (basic)
4430  * %F => 2007-11-19 Calendar date (extended)
4431  * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month
4432  * %Y => 2007 Calendar date, reduced accuracy, specific year
4433  * %C => 20 Calendar date, reduced accuracy, specific century
4434  * %Y%j => 2007323 Ordinal date (basic)
4435  * %Y-%j => 2007-323 Ordinal date (extended)
4436  * %GW%V%u => 2007W471 Week date (basic)
4437  * %G-W%V-%u => 2007-W47-1 Week date (extended)
4438  * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic)
4439  * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended)
4440  * %H%M%S => 083748 Local time (basic)
4441  * %T => 08:37:48 Local time (extended)
4442  * %H%M => 0837 Local time, reduced accuracy, specific minute (basic)
4443  * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended)
4444  * %H => 08 Local time, reduced accuracy, specific hour
4445  * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic)
4446  * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended)
4447  * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic)
4448  * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended)
4449  * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic)
4450  * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended)
4451  * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic)
4452  * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended)
4453  * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic)
4454  * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended)
4455  * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic)
4456  * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended)
4457  * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic)
4458  * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended)
4459  * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic)
4460  * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended)
4461  * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic)
4462  * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended)
4463  *
4464  */
4465 
4466 static VALUE
4467 time_strftime(VALUE time, VALUE format)
4468 {
4469  struct time_object *tobj;
4470  const char *fmt;
4471  long len;
4472  rb_encoding *enc;
4473  VALUE tmp;
4474 
4475  GetTimeval(time, tobj);
4476  MAKE_TM(time, tobj);
4477  StringValue(format);
4478  if (!rb_enc_str_asciicompat_p(format)) {
4479  rb_raise(rb_eArgError, "format should have ASCII compatible encoding");
4480  }
4481  tmp = rb_str_tmp_frozen_acquire(format);
4482  fmt = RSTRING_PTR(tmp);
4483  len = RSTRING_LEN(tmp);
4484  enc = rb_enc_get(format);
4485  if (len == 0) {
4486  rb_warning("strftime called with empty format string");
4487  return rb_enc_str_new(0, 0, enc);
4488  }
4489  else {
4490  VALUE str = rb_strftime_alloc(fmt, len, enc, &tobj->vtm, tobj->timew,
4491  TIME_UTC_P(tobj));
4492  rb_str_tmp_frozen_release(format, tmp);
4493  if (!str) rb_raise(rb_eArgError, "invalid format: %"PRIsVALUE, format);
4494  return str;
4495  }
4496 }
4497 
4498 /* :nodoc: */
4499 static VALUE
4500 time_mdump(VALUE time)
4501 {
4502  struct time_object *tobj;
4503  unsigned long p, s;
4504  char buf[8];
4505  int i;
4506  VALUE str;
4507 
4508  struct vtm vtm;
4509  long year;
4510  long usec, nsec;
4511  VALUE subsecx, nano, subnano, v;
4512 
4513  GetTimeval(time, tobj);
4514 
4515  gmtimew(tobj->timew, &vtm);
4516 
4517  if (FIXNUM_P(vtm.year)) {
4518  year = FIX2LONG(vtm.year);
4519  if (year < 1900 || 1900+0xffff < year)
4520  rb_raise(rb_eArgError, "year too big to marshal: %ld UTC", year);
4521  }
4522  else {
4523  rb_raise(rb_eArgError, "year too big to marshal");
4524  }
4525 
4526  subsecx = vtm.subsecx;
4527 
4528  nano = mulquov(subsecx, INT2FIX(1000000000), INT2FIX(TIME_SCALE));
4529  divmodv(nano, INT2FIX(1), &v, &subnano);
4530  nsec = FIX2LONG(v);
4531  usec = nsec / 1000;
4532  nsec = nsec % 1000;
4533 
4534  nano = addv(LONG2FIX(nsec), subnano);
4535 
4536  p = 0x1UL << 31 | /* 1 */
4537  TIME_UTC_P(tobj) << 30 | /* 1 */
4538  (year-1900) << 14 | /* 16 */
4539  (vtm.mon-1) << 10 | /* 4 */
4540  vtm.mday << 5 | /* 5 */
4541  vtm.hour; /* 5 */
4542  s = (unsigned long)vtm.min << 26 | /* 6 */
4543  vtm.sec << 20 | /* 6 */
4544  usec; /* 20 */
4545 
4546  for (i=0; i<4; i++) {
4547  buf[i] = (unsigned char)p;
4548  p = RSHIFT(p, 8);
4549  }
4550  for (i=4; i<8; i++) {
4551  buf[i] = (unsigned char)s;
4552  s = RSHIFT(s, 8);
4553  }
4554 
4555  str = rb_str_new(buf, 8);
4556  rb_copy_generic_ivar(str, time);
4557  if (!rb_equal(nano, INT2FIX(0))) {
4558  if (RB_TYPE_P(nano, T_RATIONAL)) {
4559  rb_ivar_set(str, id_nano_num, RRATIONAL(nano)->num);
4560  rb_ivar_set(str, id_nano_den, RRATIONAL(nano)->den);
4561  }
4562  else {
4563  rb_ivar_set(str, id_nano_num, nano);
4564  rb_ivar_set(str, id_nano_den, INT2FIX(1));
4565  }
4566  }
4567  if (nsec) { /* submicro is only for Ruby 1.9.1 compatibility */
4568  /*
4569  * submicro is formatted in fixed-point packed BCD (without sign).
4570  * It represent digits under microsecond.
4571  * For nanosecond resolution, 3 digits (2 bytes) are used.
4572  * However it can be longer.
4573  * Extra digits are ignored for loading.
4574  */
4575  char buf[2];
4576  int len = (int)sizeof(buf);
4577  buf[1] = (char)((nsec % 10) << 4);
4578  nsec /= 10;
4579  buf[0] = (char)(nsec % 10);
4580  nsec /= 10;
4581  buf[0] |= (char)((nsec % 10) << 4);
4582  if (buf[1] == 0)
4583  len = 1;
4584  rb_ivar_set(str, id_submicro, rb_str_new(buf, len));
4585  }
4586  if (!TIME_UTC_P(tobj)) {
4587  VALUE off = time_utc_offset(time), div, mod;
4588  divmodv(off, INT2FIX(1), &div, &mod);
4589  if (rb_equal(mod, INT2FIX(0)))
4590  off = rb_Integer(div);
4591  rb_ivar_set(str, id_offset, off);
4592  }
4593  if (tobj->vtm.zone) {
4594  rb_ivar_set(str, id_zone, time_zone_name(tobj->vtm.zone));
4595  }
4596  return str;
4597 }
4598 
4599 /* :nodoc: */
4600 static VALUE
4601 time_dump(int argc, VALUE *argv, VALUE time)
4602 {
4603  VALUE str;
4604 
4605  rb_scan_args(argc, argv, "01", 0);
4606  str = time_mdump(time);
4607 
4608  return str;
4609 }
4610 
4611 /* :nodoc: */
4612 static VALUE
4613 time_mload(VALUE time, VALUE str)
4614 {
4615  struct time_object *tobj;
4616  unsigned long p, s;
4617  time_t sec;
4618  long usec;
4619  unsigned char *buf;
4620  struct vtm vtm;
4621  int i, gmt;
4622  long nsec;
4623  VALUE submicro, nano_num, nano_den, offset, zone;
4624  wideval_t timew;
4625 
4626  time_modify(time);
4627 
4628 #define get_attr(attr, iffound) \
4629  attr = rb_attr_delete(str, id_##attr); \
4630  if (!NIL_P(attr)) { \
4631  iffound; \
4632  }
4633 
4634  get_attr(nano_num, {});
4635  get_attr(nano_den, {});
4636  get_attr(submicro, {});
4637  get_attr(offset, (offset = rb_rescue(validate_utc_offset, offset, NULL, Qnil)));
4638  get_attr(zone, (zone = rb_rescue(validate_zone_name, zone, NULL, Qnil)));
4639 
4640 #undef get_attr
4641 
4642  rb_copy_generic_ivar(time, str);
4643 
4644  StringValue(str);
4645  buf = (unsigned char *)RSTRING_PTR(str);
4646  if (RSTRING_LEN(str) != 8) {
4647  rb_raise(rb_eTypeError, "marshaled time format differ");
4648  }
4649 
4650  p = s = 0;
4651  for (i=0; i<4; i++) {
4652  p |= (unsigned long)buf[i]<<(8*i);
4653  }
4654  for (i=4; i<8; i++) {
4655  s |= (unsigned long)buf[i]<<(8*(i-4));
4656  }
4657 
4658  if ((p & (1UL<<31)) == 0) {
4659  gmt = 0;
4660  offset = Qnil;
4661  sec = p;
4662  usec = s;
4663  nsec = usec * 1000;
4664  timew = wadd(rb_time_magnify(TIMET2WV(sec)), wmulquoll(WINT2FIXWV(usec), TIME_SCALE, 1000000));
4665  }
4666  else {
4667  p &= ~(1UL<<31);
4668  gmt = (int)((p >> 30) & 0x1);
4669 
4670  vtm.year = INT2FIX(((int)(p >> 14) & 0xffff) + 1900);
4671  vtm.mon = ((int)(p >> 10) & 0xf) + 1;
4672  vtm.mday = (int)(p >> 5) & 0x1f;
4673  vtm.hour = (int) p & 0x1f;
4674  vtm.min = (int)(s >> 26) & 0x3f;
4675  vtm.sec = (int)(s >> 20) & 0x3f;
4676  vtm.utc_offset = INT2FIX(0);
4677  vtm.yday = vtm.wday = 0;
4678  vtm.isdst = 0;
4679  vtm.zone = "";
4680 
4681  usec = (long)(s & 0xfffff);
4682  nsec = usec * 1000;
4683 
4684 
4685  vtm.subsecx = mulquov(LONG2FIX(nsec), INT2FIX(TIME_SCALE), LONG2FIX(1000000000));
4686  if (nano_num != Qnil) {
4687  VALUE nano = quov(num_exact(nano_num), num_exact(nano_den));
4688  vtm.subsecx = addv(vtm.subsecx, mulquov(nano, INT2FIX(TIME_SCALE), LONG2FIX(1000000000)));
4689  }
4690  else if (submicro != Qnil) { /* for Ruby 1.9.1 compatibility */
4691  unsigned char *ptr;
4692  long len;
4693  int digit;
4694  ptr = (unsigned char*)StringValuePtr(submicro);
4695  len = RSTRING_LEN(submicro);
4696  nsec = 0;
4697  if (0 < len) {
4698  if (10 <= (digit = ptr[0] >> 4)) goto end_submicro;
4699  nsec += digit * 100;
4700  if (10 <= (digit = ptr[0] & 0xf)) goto end_submicro;
4701  nsec += digit * 10;
4702  }
4703  if (1 < len) {
4704  if (10 <= (digit = ptr[1] >> 4)) goto end_submicro;
4705  nsec += digit;
4706  }
4707  vtm.subsecx = addv(vtm.subsecx, mulquov(LONG2FIX(nsec), INT2FIX(TIME_SCALE), LONG2FIX(1000000000)));
4708 end_submicro: ;
4709  }
4710  timew = timegmw(&vtm);
4711  }
4712 
4713  GetNewTimeval(time, tobj);
4714  tobj->gmt = 0;
4715  tobj->tm_got = 0;
4716  tobj->timew = timew;
4717  if (gmt) {
4718  TIME_SET_UTC(tobj);
4719  }
4720  else if (!NIL_P(offset)) {
4721  time_set_utc_offset(time, offset);
4722  time_fixoff(time);
4723  }
4724  if (!NIL_P(zone)) {
4725  if (TIME_FIXOFF_P(tobj)) TIME_SET_LOCALTIME(tobj);
4726  zone = rb_fstring(zone);
4727  tobj->vtm.zone = StringValueCStr(zone);
4728  rb_ivar_set(time, id_zone, zone);
4729  }
4730 
4731  return time;
4732 }
4733 
4734 /* :nodoc: */
4735 static VALUE
4736 time_load(VALUE klass, VALUE str)
4737 {
4738  VALUE time = time_s_alloc(klass);
4739 
4740  time_mload(time, str);
4741  return time;
4742 }
4743 
4744 /*
4745  * Time is an abstraction of dates and times. Time is stored internally as
4746  * the number of seconds with fraction since the _Epoch_, January 1, 1970
4747  * 00:00 UTC. Also see the library module Date. The Time class treats GMT
4748  * (Greenwich Mean Time) and UTC (Coordinated Universal Time) as equivalent.
4749  * GMT is the older way of referring to these baseline times but persists in
4750  * the names of calls on POSIX systems.
4751  *
4752  * All times may have fraction. Be aware of this fact when comparing times
4753  * with each other -- times that are apparently equal when displayed may be
4754  * different when compared.
4755  *
4756  * Since Ruby 1.9.2, Time implementation uses a signed 63 bit integer,
4757  * Bignum or Rational.
4758  * The integer is a number of nanoseconds since the _Epoch_ which can
4759  * represent 1823-11-12 to 2116-02-20.
4760  * When Bignum or Rational is used (before 1823, after 2116, under
4761  * nanosecond), Time works slower as when integer is used.
4762  *
4763  * = Examples
4764  *
4765  * All of these examples were done using the EST timezone which is GMT-5.
4766  *
4767  * == Creating a new Time instance
4768  *
4769  * You can create a new instance of Time with Time::new. This will use the
4770  * current system time. Time::now is an alias for this. You can also
4771  * pass parts of the time to Time::new such as year, month, minute, etc. When
4772  * you want to construct a time this way you must pass at least a year. If you
4773  * pass the year with nothing else time will default to January 1 of that year
4774  * at 00:00:00 with the current system timezone. Here are some examples:
4775  *
4776  * Time.new(2002) #=> 2002-01-01 00:00:00 -0500
4777  * Time.new(2002, 10) #=> 2002-10-01 00:00:00 -0500
4778  * Time.new(2002, 10, 31) #=> 2002-10-31 00:00:00 -0500
4779  * Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200
4780  *
4781  * You can also use #gm, #local and
4782  * #utc to infer GMT, local and UTC timezones instead of using
4783  * the current system setting.
4784  *
4785  * You can also create a new time using Time::at which takes the number of
4786  * seconds (or fraction of seconds) since the {Unix
4787  * Epoch}[http://en.wikipedia.org/wiki/Unix_time].
4788  *
4789  * Time.at(628232400) #=> 1989-11-28 00:00:00 -0500
4790  *
4791  * == Working with an instance of Time
4792  *
4793  * Once you have an instance of Time there is a multitude of things you can
4794  * do with it. Below are some examples. For all of the following examples, we
4795  * will work on the assumption that you have done the following:
4796  *
4797  * t = Time.new(1993, 02, 24, 12, 0, 0, "+09:00")
4798  *
4799  * Was that a monday?
4800  *
4801  * t.monday? #=> false
4802  *
4803  * What year was that again?
4804  *
4805  * t.year #=> 1993
4806  *
4807  * Was it daylight savings at the time?
4808  *
4809  * t.dst? #=> false
4810  *
4811  * What's the day a year later?
4812  *
4813  * t + (60*60*24*365) #=> 1994-02-24 12:00:00 +0900
4814  *
4815  * How many seconds was that since the Unix Epoch?
4816  *
4817  * t.to_i #=> 730522800
4818  *
4819  * You can also do standard functions like compare two times.
4820  *
4821  * t1 = Time.new(2010)
4822  * t2 = Time.new(2011)
4823  *
4824  * t1 == t2 #=> false
4825  * t1 == t1 #=> true
4826  * t1 < t2 #=> true
4827  * t1 > t2 #=> false
4828  *
4829  * Time.new(2010,10,31).between?(t1, t2) #=> true
4830  */
4831 
4832 void
4834 {
4835 #undef rb_intern
4836 #define rb_intern(str) rb_intern_const(str)
4837 
4838  id_quo = rb_intern("quo");
4839  id_div = rb_intern("div");
4840  id_divmod = rb_intern("divmod");
4841  id_submicro = rb_intern("submicro");
4842  id_nano_num = rb_intern("nano_num");
4843  id_nano_den = rb_intern("nano_den");
4844  id_offset = rb_intern("offset");
4845  id_zone = rb_intern("zone");
4846  id_nanosecond = rb_intern("nanosecond");
4847  id_microsecond = rb_intern("microsecond");
4848  id_millisecond = rb_intern("millisecond");
4849  id_nsec = rb_intern("nsec");
4850  id_usec = rb_intern("usec");
4851 
4852  rb_cTime = rb_define_class("Time", rb_cObject);
4854 
4855  rb_define_alloc_func(rb_cTime, time_s_alloc);
4856  rb_define_singleton_method(rb_cTime, "now", time_s_now, 0);
4857  rb_define_singleton_method(rb_cTime, "at", time_s_at, -1);
4858  rb_define_singleton_method(rb_cTime, "utc", time_s_mkutc, -1);
4859  rb_define_singleton_method(rb_cTime, "gm", time_s_mkutc, -1);
4860  rb_define_singleton_method(rb_cTime, "local", time_s_mktime, -1);
4861  rb_define_singleton_method(rb_cTime, "mktime", time_s_mktime, -1);
4862 
4863  rb_define_method(rb_cTime, "to_i", time_to_i, 0);
4864  rb_define_method(rb_cTime, "to_f", time_to_f, 0);
4865  rb_define_method(rb_cTime, "to_r", time_to_r, 0);
4866  rb_define_method(rb_cTime, "<=>", time_cmp, 1);
4867  rb_define_method(rb_cTime, "eql?", time_eql, 1);
4868  rb_define_method(rb_cTime, "hash", time_hash, 0);
4869  rb_define_method(rb_cTime, "initialize", time_init, -1);
4870  rb_define_method(rb_cTime, "initialize_copy", time_init_copy, 1);
4871 
4872  rb_define_method(rb_cTime, "localtime", time_localtime_m, -1);
4873  rb_define_method(rb_cTime, "gmtime", time_gmtime, 0);
4874  rb_define_method(rb_cTime, "utc", time_gmtime, 0);
4875  rb_define_method(rb_cTime, "getlocal", time_getlocaltime, -1);
4876  rb_define_method(rb_cTime, "getgm", time_getgmtime, 0);
4877  rb_define_method(rb_cTime, "getutc", time_getgmtime, 0);
4878 
4879  rb_define_method(rb_cTime, "ctime", time_asctime, 0);
4880  rb_define_method(rb_cTime, "asctime", time_asctime, 0);
4881  rb_define_method(rb_cTime, "to_s", time_to_s, 0);
4882  rb_define_method(rb_cTime, "inspect", time_to_s, 0);
4883  rb_define_method(rb_cTime, "to_a", time_to_a, 0);
4884 
4885  rb_define_method(rb_cTime, "+", time_plus, 1);
4886  rb_define_method(rb_cTime, "-", time_minus, 1);
4887 
4888  rb_define_method(rb_cTime, "succ", time_succ, 0);
4889  rb_define_method(rb_cTime, "round", time_round, -1);
4890 
4891  rb_define_method(rb_cTime, "sec", time_sec, 0);
4892  rb_define_method(rb_cTime, "min", time_min, 0);
4893  rb_define_method(rb_cTime, "hour", time_hour, 0);
4894  rb_define_method(rb_cTime, "mday", time_mday, 0);
4895  rb_define_method(rb_cTime, "day", time_mday, 0);
4896  rb_define_method(rb_cTime, "mon", time_mon, 0);
4897  rb_define_method(rb_cTime, "month", time_mon, 0);
4898  rb_define_method(rb_cTime, "year", time_year, 0);
4899  rb_define_method(rb_cTime, "wday", time_wday, 0);
4900  rb_define_method(rb_cTime, "yday", time_yday, 0);
4901  rb_define_method(rb_cTime, "isdst", time_isdst, 0);
4902  rb_define_method(rb_cTime, "dst?", time_isdst, 0);
4903  rb_define_method(rb_cTime, "zone", time_zone, 0);
4904  rb_define_method(rb_cTime, "gmtoff", time_utc_offset, 0);
4905  rb_define_method(rb_cTime, "gmt_offset", time_utc_offset, 0);
4906  rb_define_method(rb_cTime, "utc_offset", time_utc_offset, 0);
4907 
4908  rb_define_method(rb_cTime, "utc?", time_utc_p, 0);
4909  rb_define_method(rb_cTime, "gmt?", time_utc_p, 0);
4910 
4911  rb_define_method(rb_cTime, "sunday?", time_sunday, 0);
4912  rb_define_method(rb_cTime, "monday?", time_monday, 0);
4913  rb_define_method(rb_cTime, "tuesday?", time_tuesday, 0);
4914  rb_define_method(rb_cTime, "wednesday?", time_wednesday, 0);
4915  rb_define_method(rb_cTime, "thursday?", time_thursday, 0);
4916  rb_define_method(rb_cTime, "friday?", time_friday, 0);
4917  rb_define_method(rb_cTime, "saturday?", time_saturday, 0);
4918 
4919  rb_define_method(rb_cTime, "tv_sec", time_to_i, 0);
4920  rb_define_method(rb_cTime, "tv_usec", time_usec, 0);
4921  rb_define_method(rb_cTime, "usec", time_usec, 0);
4922  rb_define_method(rb_cTime, "tv_nsec", time_nsec, 0);
4923  rb_define_method(rb_cTime, "nsec", time_nsec, 0);
4924  rb_define_method(rb_cTime, "subsec", time_subsec, 0);
4925 
4926  rb_define_method(rb_cTime, "strftime", time_strftime, 1);
4927 
4928  /* methods for marshaling */
4929  rb_define_private_method(rb_cTime, "_dump", time_dump, -1);
4930  rb_define_private_method(rb_singleton_class(rb_cTime), "_load", time_load, 1);
4931 #if 0
4932  /* Time will support marshal_dump and marshal_load in the future (1.9 maybe) */
4933  rb_define_private_method(rb_cTime, "marshal_dump", time_mdump, 0);
4934  rb_define_private_method(rb_cTime, "marshal_load", time_mload, 1);
4935 #endif
4936 
4937 #ifdef DEBUG_FIND_TIME_NUMGUESS
4938  rb_define_virtual_variable("$find_time_numguess", find_time_numguess_getter, NULL);
4939 #endif
4940 }
#define STRNCASECMP(s1, s2, n)
Definition: ruby.h:2159
VALUE rb_big_modulo(VALUE x, VALUE y)
Definition: bignum.c:6048
VALUE rb_hash(VALUE obj)
Definition: hash.c:121
#define ISDIGIT(c)
Definition: ruby.h:2150
VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc)
Definition: string.c:1042
#define WINT2FIXWV(i)
Definition: time.c:215
#define WV2TIMET(t)
Definition: time.c:622
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Definition: bignum.c:3529
void rb_warn(const char *fmt,...)
Definition: error.c:246
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1215
int gettimeofday(struct timeval *, struct timezone *)
Definition: win32.c:4596
#define FALSE
Definition: nkf.h:174
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
#define INT2NUM(x)
Definition: ruby.h:1538
Definition: st.h:79
Definition: st.h:99
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:648
#define NUM2INT(x)
Definition: ruby.h:684
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
Definition: object.c:3099
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
Definition: string.c:1183
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
long wideint_t
Definition: time.c:204
#define GUESS(p)
void rb_timespec_now(struct timespec *ts)
Definition: time.c:1749
#define GetTimeval(obj, tobj)
Definition: time.c:1607
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
VALUE rb_time_timespec_new(const struct timespec *ts, int offset)
Returns a time object with UTC/localtime/fixed offset.
Definition: time.c:2181
#define Qtrue
Definition: ruby.h:437
#define OBJ_INIT_COPY(obj, orig)
Definition: intern.h:283
Definition: st.h:99
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1183
VALUE rb_big_plus(VALUE x, VALUE y)
Definition: bignum.c:5772
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2299
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1527
#define FIXNUM_MIN
Definition: ruby.h:229
void rb_check_trusted(VALUE obj)
Definition: error.c:2622
#define T_RATIONAL
Definition: ruby.h:509
#define rb_long2int(n)
Definition: ruby.h:319
VALUE rb_strftime_timespec(const char *format, size_t format_len, rb_encoding *enc, const struct vtm *vtm, struct timespec *ts, int gmt)
Definition: strftime.c:925
#define DEBUG_REPORT_GUESSRANGE
Definition: time.c:2669
#define WIDEVAL_GET(w)
Definition: time.c:235
#define NDIV(x, y)
Definition: time.c:41
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
#define INTEGER_PACK_NATIVE_BYTE_ORDER
Definition: intern.h:142
VALUE rb_time_succ(VALUE time)
Definition: time.c:3718
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:854
VALUE rb_strftime(const char *format, size_t format_len, rb_encoding *enc, const struct vtm *vtm, VALUE timev, int gmt)
Definition: strftime.c:915
#define IsTimeval(obj)
Definition: time.c:1610
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
An equivalent of rescue clause.
Definition: eval.c:967
#define RB_GC_GUARD(v)
Definition: ruby.h:552
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_Integer(VALUE)
Equivalent to Kernel#Integer in Ruby.
Definition: object.c:3148
#define DATA_PTR(dta)
Definition: ruby.h:1106
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:864
#define leap_year_v_p(y)
Definition: time.c:648
void rb_gc_mark(VALUE ptr)
Definition: gc.c:4464
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:1393
#define FIXWV2WINT(w)
Definition: time.c:216
#define TIME_LOCALTIME_P(tobj)
Definition: time.c:1616
time_t tv_sec
Definition: missing.h:54
#define FIXNUM_P(f)
Definition: ruby.h:365
#define st_init_strtable
Definition: regint.h:180
#define VTM_ISDST_INITVAL
Definition: time.c:46
#define WINT2WV(wi)
Definition: time.c:249
unsigned char uint8_t
Definition: sha2.h:100
VALUE rb_eArgError
Definition: error.c:802
time_t tv_sec
Definition: missing.h:61
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:22
#define TIME_UTC_P(tobj)
Definition: time.c:1613
#define WIDEVAL_WRAP(v)
Definition: time.c:234
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
Definition: class.c:1689
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class
Definition: object.c:277
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
#define neg(x)
Definition: time.c:131
unsigned long uwideint_t
Definition: time.c:203
#define le(x, y)
Definition: time.c:75
VALUE rb_eRangeError
Definition: error.c:805
unsigned long long uint64_t
Definition: sha2.h:102
VALUE rb_mComparable
Definition: compar.c:15
#define validate_vtm_range(mem, b, e)
#define GetNewTimeval(obj, tobj)
Definition: time.c:1608
#define div(x, y)
Definition: date_strftime.c:27
VALUE rb_equal(VALUE, VALUE)
call-seq: obj === other -> true or false
Definition: object.c:126
long tv_usec
Definition: missing.h:55
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
#define get_attr(attr, iffound)
VALUE rb_time_new(time_t sec, long usec)
Definition: time.c:2143
#define ne(x, y)
Definition: time.c:72
#define wmulquoll(x, y, z)
Definition: time.c:401
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
Definition: bignum.c:4226
#define TIME_SET_UTC(tobj)
Definition: time.c:1614
#define LOCALTIME(tm, result)
Definition: time.c:681
#define TIME_FIXOFF_P(tobj)
Definition: time.c:1619
VALUE rb_big_cmp(VALUE x, VALUE y)
Definition: bignum.c:5367
#define RRATIONAL(obj)
Definition: internal.h:630
#define FIXWVABLE(i)
Definition: time.c:214
#define NIL_P(v)
Definition: ruby.h:451
long tv_nsec
Definition: missing.h:62
#define VTM_WDAY_INITVAL
Definition: time.c:45
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:646
struct tm * localtime_r(const time_t *, struct tm *)
Definition: win32.c:7796
VALUE WIDEVALUE
Definition: time.c:205
#define GMTIME(tm, result)
Definition: time.c:700
#define rb_intern(str)
int argc
Definition: ruby.c:187
PACKED_STRUCT_UNALIGNED(struct time_object { wideval_t timew;struct vtm vtm;uint8_t gmt:3;uint8_t tm_got:1;})
#define Qfalse
Definition: ruby.h:436
#define TIME_INIT_P(tobj)
Definition: time.c:1611
#define FIXWV_MIN
Definition: time.c:213
WIDEVALUE wideval_t
Definition: time.c:233
#define T_BIGNUM
Definition: ruby.h:501
#define FIXWV_P(w)
Definition: time.c:221
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1661
void rb_num_zerodiv(void)
Definition: numeric.c:192
Definition: id.h:82
void rb_sys_fail(const char *mesg)
Definition: error.c:2403
void Init_Time(void)
Definition: time.c:4833
VALUE rb_big_minus(VALUE x, VALUE y)
Definition: bignum.c:5801
#define RSTRING_LEN(str)
Definition: ruby.h:971
#define TRUE
Definition: nkf.h:175
#define CLOCK_REALTIME
Definition: win32.h:133
VALUE rb_big_div(VALUE x, VALUE y)
Definition: bignum.c:6036
#define time_succ
Definition: time.c:3731
#define rb_Rational1(x)
Definition: intern.h:169
#define strdup(s)
Definition: util.h:70
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1315
#define TIME_COPY_GMT(tobj1, tobj2)
Definition: time.c:1625
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1335
#define mulquov(x, y, z)
Definition: time.c:156
#define Qnil
Definition: ruby.h:438
#define TIMET2WV(t)
Definition: time.c:599
#define TO_GMT_INITVAL
Definition: time.c:47
unsigned long VALUE
Definition: ruby.h:85
VALUE rb_big_mul(VALUE x, VALUE y)
Definition: bignum.c:5881
rb_encoding * rb_locale_encoding(void)
Definition: encoding.c:1370
#define rb_enc_str_asciicompat_p(str)
Definition: encoding.h:251
VALUE rb_eTypeError
Definition: error.c:801
#define FIX2INT(x)
Definition: ruby.h:686
#define rb_ary_new3
Definition: intern.h:91
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:389
int clock_gettime(clockid_t, struct timespec *)
Definition: win32.c:4608
VALUE rb_time_nano_new(time_t sec, long nsec)
Definition: time.c:2170
#define rb_cmpint(cmp, a, b)
#define DIV(n, d)
Definition: time.c:43
VALUE rb_str_new_cstr(const char *)
Definition: string.c:771
size_t rb_absint_size(VALUE val, int *nlz_bits_ret)
Definition: bignum.c:3229
#define MUL_OVERFLOW_FIXWV_P(a, b)
Definition: time.c:222
VALUE rb_fstring(VALUE)
Definition: string.c:306
#define ge(x, y)
Definition: time.c:76
#define RB_FLOAT_TYPE_P(obj)
Definition: ruby.h:523
#define _(args)
Definition: dln.h:28
#define TYPEOF_TIMEVAL_TV_USEC
Definition: timev.h:28
#define LONG2NUM(x)
Definition: ruby.h:1573
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1994
unsigned int uint32_t
Definition: sha2.h:101
register unsigned int len
Definition: zonetab.h:51
#define StringValueCStr(v)
Definition: ruby.h:571
#define RSTRING_PTR(str)
Definition: ruby.h:975
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:860
#define wlt(x, y)
Definition: time.c:341
#define RFLOAT_VALUE(v)
Definition: ruby.h:933
#define f
#define INT2FIX(i)
Definition: ruby.h:232
#define TIME_SET_LOCALTIME(tobj)
Definition: time.c:1617
VALUE rb_Float(VALUE)
Equivalent to Kernel#Float in Ruby.
Definition: object.c:3398
#define MOD(n, d)
Definition: time.c:44
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:651
#define TIME_SET_FIXOFF(tobj, off)
Definition: time.c:1620
#define MAKE_TM(time, tobj)
Definition: time.c:1631
VALUE rb_check_string_type(VALUE)
Definition: string.c:2246
#define gt(x, y)
Definition: time.c:74
struct timespec rb_time_timespec(VALUE time)
Definition: time.c:2322
#define LONG2FIX(i)
Definition: ruby.h:234
#define RTEST(v)
Definition: ruby.h:450
void rb_warning(const char *fmt,...)
Definition: error.c:267
#define T_STRING
Definition: ruby.h:496
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:2170
SIGNED_VALUE SIGNED_WIDEVALUE
Definition: time.c:206
Definition: zonetab.h:34
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
struct tm * gmtime_r(const time_t *, struct tm *)
Definition: win32.c:7772
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:759
const char * name
Definition: nkf.c:208
#define digit(x)
Definition: langinfo.c:58
#define ID2SYM(x)
Definition: ruby.h:383
VALUE rb_cTime
Definition: time.c:624
#define StringValuePtr(v)
Definition: ruby.h:570
#define FIXWV_MAX
Definition: time.c:212
VALUE rb_numeric_quo(VALUE x, VALUE y)
Definition: rational.c:2042
#define TIME_SCALE
Definition: timev.h:19
#define lt(x, y)
Definition: time.c:73
#define rb_check_frozen(obj)
Definition: intern.h:271
VALUE rb_str_tmp_frozen_acquire(VALUE str)
Definition: string.c:1170
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1134
void rb_copy_generic_ivar(VALUE, VALUE)
Definition: variable.c:1502
Definition: id.h:94
int rb_enc_str_asciionly_p(VALUE)
Definition: string.c:641
#define mod(x, y)
Definition: date_strftime.c:28
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
#define NULL
Definition: _sdbm.c:102
#define FIX2LONG(x)
Definition: ruby.h:363
#define Qundef
Definition: ruby.h:439
VALUE rb_invcmp(VALUE x, VALUE y)
Definition: compar.c:46
#define id_quo
Definition: rational.c:1641
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
#define strftimev(fmt, time, enc)
Definition: time.c:3576
#define NUM2LONG(x)
Definition: ruby.h:648
struct timeval rb_time_timeval(VALUE time)
Definition: time.c:2305
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3084
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1224
VALUE rb_usascii_str_new_cstr(const char *)
Definition: string.c:778
#define TYPEOF_TIMEVAL_TV_SEC
Definition: timev.h:22
char ** argv
Definition: ruby.c:188
#define DBL2NUM(dbl)
Definition: ruby.h:934
#define StringValue(v)
Definition: ruby.h:569
#define wday_p(n)
Definition: time.c:3963
VALUE rb_str_new(const char *, long)
Definition: string.c:737
#define SIGNED_VALUE
Definition: ruby.h:87
VALUE rb_time_num_new(VALUE timev, VALUE off)
Definition: time.c:2204