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