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