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