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