source: EcnlProtoTool/trunk/mruby-1.2.0/mrbgems/mruby-time/src/time.c@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 22.8 KB
Line 
1/*
2** time.c - Time class
3**
4** See Copyright Notice in mruby.h
5*/
6
7#include <math.h>
8#include <stdio.h>
9#include <time.h>
10#include "mruby.h"
11#include "mruby/class.h"
12#include "mruby/data.h"
13
14#if !defined(__MINGW64__) && defined(_WIN32)
15# define llround(x) round(x)
16#endif
17
18#if defined(__MINGW64__) || defined(__MINGW32__)
19# include <sys/time.h>
20#endif
21
22/** Time class configuration */
23
24/* gettimeofday(2) */
25/* C99 does not have gettimeofday that is required to retrieve microseconds */
26/* uncomment following macro on platforms without gettimeofday(2) */
27/* #define NO_GETTIMEOFDAY */
28
29/* gmtime(3) */
30/* C99 does not have reentrant gmtime_r() so it might cause troubles under */
31/* multi-threading environment. undef following macro on platforms that */
32/* does not have gmtime_r() and localtime_r(). */
33/* #define NO_GMTIME_R */
34
35#ifdef _WIN32
36#if _MSC_VER
37/* Win32 platform do not provide gmtime_r/localtime_r; emulate them using gmtime_s/localtime_s */
38#define gmtime_r(tp, tm) ((gmtime_s((tm), (tp)) == 0) ? (tm) : NULL)
39#define localtime_r(tp, tm) ((localtime_s((tm), (tp)) == 0) ? (tm) : NULL)
40#else
41#define NO_GMTIME_R
42#endif
43#endif
44
45/* timegm(3) */
46/* mktime() creates tm structure for localtime; timegm() is for UTC time */
47/* define following macro to use probably faster timegm() on the platform */
48/* #define USE_SYSTEM_TIMEGM */
49
50/** end of Time class configuration */
51
52#ifndef NO_GETTIMEOFDAY
53# ifdef _WIN32
54# define WIN32_LEAN_AND_MEAN /* don't include winsock.h */
55# include <windows.h>
56# define gettimeofday my_gettimeofday
57
58# ifdef _MSC_VER
59# define UI64(x) x##ui64
60# else
61# define UI64(x) x##ull
62# endif
63
64typedef long suseconds_t;
65
66# if (!defined __MINGW64__) && (!defined __MINGW32__)
67struct timeval {
68 time_t tv_sec;
69 suseconds_t tv_usec;
70};
71# endif
72
73static int
74gettimeofday(struct timeval *tv, void *tz)
75{
76 if (tz) {
77 mrb_assert(0); /* timezone is not supported */
78 }
79 if (tv) {
80 union {
81 FILETIME ft;
82 unsigned __int64 u64;
83 } t;
84 GetSystemTimeAsFileTime(&t.ft); /* 100 ns intervals since Windows epoch */
85 t.u64 -= UI64(116444736000000000); /* Unix epoch bias */
86 t.u64 /= 10; /* to microseconds */
87 tv->tv_sec = (time_t)(t.u64 / (1000 * 1000));
88 tv->tv_usec = t.u64 % (1000 * 1000);
89 }
90 return 0;
91}
92# else
93# include <sys/time.h>
94# endif
95#endif
96#ifdef NO_GMTIME_R
97#define gmtime_r(t,r) gmtime(t)
98#define localtime_r(t,r) localtime(t)
99#endif
100
101#ifndef USE_SYSTEM_TIMEGM
102#define timegm my_timgm
103
104static unsigned int
105is_leapyear(unsigned int y)
106{
107 return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
108}
109
110static time_t
111timegm(struct tm *tm)
112{
113 static const unsigned int ndays[2][12] = {
114 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
115 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
116 };
117 time_t r = 0;
118 int i;
119 unsigned int *nday = (unsigned int*) ndays[is_leapyear(tm->tm_year+1900)];
120
121 for (i = 70; i < tm->tm_year; ++i)
122 r += is_leapyear(i+1900) ? 366*24*60*60 : 365*24*60*60;
123 for (i = 0; i < tm->tm_mon; ++i)
124 r += nday[i] * 24 * 60 * 60;
125 r += (tm->tm_mday - 1) * 24 * 60 * 60;
126 r += tm->tm_hour * 60 * 60;
127 r += tm->tm_min * 60;
128 r += tm->tm_sec;
129 return r;
130}
131#endif
132
133/* Since we are limited to using ISO C99, this implementation is based
134* on time_t. That means the resolution of time is only precise to the
135* second level. Also, there are only 2 timezones, namely UTC and LOCAL.
136*/
137
138enum mrb_timezone {
139 MRB_TIMEZONE_NONE = 0,
140 MRB_TIMEZONE_UTC = 1,
141 MRB_TIMEZONE_LOCAL = 2,
142 MRB_TIMEZONE_LAST = 3
143};
144
145typedef struct mrb_timezone_name {
146 const char name[8];
147 size_t len;
148} mrb_timezone_name;
149
150static const mrb_timezone_name timezone_names[] = {
151 { "none", sizeof("none") - 1 },
152 { "UTC", sizeof("UTC") - 1 },
153 { "LOCAL", sizeof("LOCAL") - 1 },
154};
155
156static const char mon_names[12][4] = {
157 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
158};
159
160static const char wday_names[7][4] = {
161 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
162};
163
164struct mrb_time {
165 time_t sec;
166 time_t usec;
167 enum mrb_timezone timezone;
168 struct tm datetime;
169};
170
171static const struct mrb_data_type mrb_time_type = { "Time", mrb_free };
172
173/** Updates the datetime of a mrb_time based on it's timezone and
174seconds setting. Returns self on success, NULL of failure. */
175static struct mrb_time*
176mrb_time_update_datetime(struct mrb_time *self)
177{
178 struct tm *aid;
179
180 if (self->timezone == MRB_TIMEZONE_UTC) {
181 aid = gmtime_r(&self->sec, &self->datetime);
182 }
183 else {
184 aid = localtime_r(&self->sec, &self->datetime);
185 }
186 if (!aid) return NULL;
187#ifdef NO_GMTIME_R
188 self->datetime = *aid; /* copy data */
189#endif
190
191 return self;
192}
193
194static mrb_value
195mrb_time_wrap(mrb_state *mrb, struct RClass *tc, struct mrb_time *tm)
196{
197 return mrb_obj_value(Data_Wrap_Struct(mrb, tc, &mrb_time_type, tm));
198}
199
200
201/* Allocates a mrb_time object and initializes it. */
202static struct mrb_time*
203time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone)
204{
205 struct mrb_time *tm;
206
207 tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time));
208 if (sizeof(time_t) == 4 && (sec > (double)INT32_MAX || (double)INT32_MIN > sec)) {
209 goto out_of_range;
210 }
211 if (sizeof(time_t) == 8 && (sec > (double)INT64_MAX || (double)INT64_MIN > sec)) {
212 goto out_of_range;
213 }
214 tm->sec = (time_t)sec;
215 if ((sec > 0 && tm->sec < 0) || (sec < 0 && (double)tm->sec > sec)) {
216 out_of_range:
217 mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, sec));
218 }
219 tm->usec = (time_t)llround((sec - tm->sec) * 1.0e6 + usec);
220 while (tm->usec < 0) {
221 tm->sec--;
222 tm->usec += 1000000;
223 }
224 while (tm->usec >= 1000000) {
225 tm->sec++;
226 tm->usec -= 1000000;
227 }
228 tm->timezone = timezone;
229 mrb_time_update_datetime(tm);
230
231 return tm;
232}
233
234static mrb_value
235mrb_time_make(mrb_state *mrb, struct RClass *c, double sec, double usec, enum mrb_timezone timezone)
236{
237 return mrb_time_wrap(mrb, c, time_alloc(mrb, sec, usec, timezone));
238}
239
240static struct mrb_time*
241current_mrb_time(mrb_state *mrb)
242{
243 struct mrb_time *tm;
244
245 tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
246#if defined(TIME_UTC)
247 {
248 struct timespec ts;
249 if (timespec_get(&ts, TIME_UTC) == 0) {
250 mrb_free(mrb, tm);
251 mrb_raise(mrb, E_RUNTIME_ERROR, "timespec_get() failed for unknown reasons");
252 }
253 tm->sec = ts.tv_sec;
254 tm->usec = ts.tv_nsec / 1000;
255 }
256#elif defined(NO_GETTIMEOFDAY)
257 {
258 static time_t last_sec = 0, last_usec = 0;
259
260 tm->sec = time(NULL);
261 if (tm->sec != last_sec) {
262 last_sec = tm->sec;
263 last_usec = 0;
264 }
265 else {
266 /* add 1 usec to differentiate two times */
267 last_usec += 1;
268 }
269 tm->usec = last_usec;
270 }
271#else
272 {
273 struct timeval tv;
274
275 gettimeofday(&tv, NULL);
276 tm->sec = tv.tv_sec;
277 tm->usec = tv.tv_usec;
278 }
279#endif
280 tm->timezone = MRB_TIMEZONE_LOCAL;
281 mrb_time_update_datetime(tm);
282
283 return tm;
284}
285
286/* Allocates a new Time object with given millis value. */
287static mrb_value
288mrb_time_now(mrb_state *mrb, mrb_value self)
289{
290 return mrb_time_wrap(mrb, mrb_class_ptr(self), current_mrb_time(mrb));
291}
292
293/* 15.2.19.6.1 */
294/* Creates an instance of time at the given time in seconds, etc. */
295static mrb_value
296mrb_time_at(mrb_state *mrb, mrb_value self)
297{
298 mrb_float f, f2 = 0;
299
300 mrb_get_args(mrb, "f|f", &f, &f2);
301 return mrb_time_make(mrb, mrb_class_ptr(self), f, f2, MRB_TIMEZONE_LOCAL);
302}
303
304static struct mrb_time*
305time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
306 mrb_int ahour, mrb_int amin, mrb_int asec, mrb_int ausec,
307 enum mrb_timezone timezone)
308{
309 time_t nowsecs;
310 struct tm nowtime = { 0 };
311
312 nowtime.tm_year = (int)ayear - 1900;
313 nowtime.tm_mon = (int)amonth - 1;
314 nowtime.tm_mday = (int)aday;
315 nowtime.tm_hour = (int)ahour;
316 nowtime.tm_min = (int)amin;
317 nowtime.tm_sec = (int)asec;
318 nowtime.tm_isdst = -1;
319 if (timezone == MRB_TIMEZONE_UTC) {
320 nowsecs = timegm(&nowtime);
321 }
322 else {
323 nowsecs = mktime(&nowtime);
324 }
325 if (nowsecs == (time_t)-1) {
326 mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time.");
327 }
328
329 return time_alloc(mrb, (double)nowsecs, ausec, timezone);
330}
331
332/* 15.2.19.6.2 */
333/* Creates an instance of time at the given time in UTC. */
334static mrb_value
335mrb_time_gm(mrb_state *mrb, mrb_value self)
336{
337 mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0, amin = 0, asec = 0, ausec = 0;
338
339 mrb_get_args(mrb, "i|iiiiii",
340 &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
341 return mrb_time_wrap(mrb, mrb_class_ptr(self),
342 time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_UTC));
343}
344
345
346/* 15.2.19.6.3 */
347/* Creates an instance of time at the given time in local time zone. */
348static mrb_value
349mrb_time_local(mrb_state *mrb, mrb_value self)
350{
351 mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0, amin = 0, asec = 0, ausec = 0;
352
353 mrb_get_args(mrb, "i|iiiiii",
354 &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
355 return mrb_time_wrap(mrb, mrb_class_ptr(self),
356 time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL));
357}
358
359
360static mrb_value
361mrb_time_eq(mrb_state *mrb, mrb_value self)
362{
363 mrb_value other;
364 struct mrb_time *tm1, *tm2;
365 mrb_bool eq_p;
366
367 mrb_get_args(mrb, "o", &other);
368 tm1 = DATA_CHECK_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
369 tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
370 eq_p = tm1 && tm2 && tm1->sec == tm2->sec && tm1->usec == tm2->usec;
371
372 return mrb_bool_value(eq_p);
373}
374
375static mrb_value
376mrb_time_cmp(mrb_state *mrb, mrb_value self)
377{
378 mrb_value other;
379 struct mrb_time *tm1, *tm2;
380
381 mrb_get_args(mrb, "o", &other);
382 tm1 = DATA_CHECK_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
383 tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
384 if (!tm1 || !tm2) return mrb_nil_value();
385 if (tm1->sec > tm2->sec) {
386 return mrb_fixnum_value(1);
387 }
388 else if (tm1->sec < tm2->sec) {
389 return mrb_fixnum_value(-1);
390 }
391 /* tm1->sec == tm2->sec */
392 if (tm1->usec > tm2->usec) {
393 return mrb_fixnum_value(1);
394 }
395 else if (tm1->usec < tm2->usec) {
396 return mrb_fixnum_value(-1);
397 }
398 return mrb_fixnum_value(0);
399}
400
401static mrb_value
402mrb_time_plus(mrb_state *mrb, mrb_value self)
403{
404 mrb_float f;
405 struct mrb_time *tm;
406
407 mrb_get_args(mrb, "f", &f);
408 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
409 return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, (double)tm->usec, tm->timezone);
410}
411
412static mrb_value
413mrb_time_minus(mrb_state *mrb, mrb_value self)
414{
415 mrb_float f;
416 mrb_value other;
417 struct mrb_time *tm, *tm2;
418
419 mrb_get_args(mrb, "o", &other);
420 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
421
422 tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
423 if (tm2) {
424 f = (mrb_float)(tm->sec - tm2->sec)
425 + (mrb_float)(tm->usec - tm2->usec) / 1.0e6;
426 return mrb_float_value(mrb, f);
427 }
428 else {
429 mrb_get_args(mrb, "f", &f);
430 return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec-f, (double)tm->usec, tm->timezone);
431 }
432}
433
434/* 15.2.19.7.30 */
435/* Returns week day number of time. */
436static mrb_value
437mrb_time_wday(mrb_state *mrb, mrb_value self)
438{
439 struct mrb_time *tm;
440
441 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
442 return mrb_fixnum_value(tm->datetime.tm_wday);
443}
444
445/* 15.2.19.7.31 */
446/* Returns year day number of time. */
447static mrb_value
448mrb_time_yday(mrb_state *mrb, mrb_value self)
449{
450 struct mrb_time *tm;
451
452 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
453 return mrb_fixnum_value(tm->datetime.tm_yday + 1);
454}
455
456/* 15.2.19.7.32 */
457/* Returns year of time. */
458static mrb_value
459mrb_time_year(mrb_state *mrb, mrb_value self)
460{
461 struct mrb_time *tm;
462
463 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
464 return mrb_fixnum_value(tm->datetime.tm_year + 1900);
465}
466
467/* 15.2.19.7.33 */
468/* Returns name of time's timezone. */
469static mrb_value
470mrb_time_zone(mrb_state *mrb, mrb_value self)
471{
472 struct mrb_time *tm;
473
474 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
475 if (tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value();
476 if (tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value();
477 return mrb_str_new_static(mrb,
478 timezone_names[tm->timezone].name,
479 timezone_names[tm->timezone].len);
480}
481
482/* 15.2.19.7.4 */
483/* Returns a string that describes the time. */
484static mrb_value
485mrb_time_asctime(mrb_state *mrb, mrb_value self)
486{
487 struct mrb_time *tm;
488 struct tm *d;
489 char buf[256];
490 int len;
491
492 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
493 d = &tm->datetime;
494 len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d",
495 wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday,
496 d->tm_hour, d->tm_min, d->tm_sec,
497 tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "",
498 d->tm_year + 1900);
499 return mrb_str_new(mrb, buf, len);
500}
501
502/* 15.2.19.7.6 */
503/* Returns the day in the month of the time. */
504static mrb_value
505mrb_time_day(mrb_state *mrb, mrb_value self)
506{
507 struct mrb_time *tm;
508
509 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
510 if (!tm) return mrb_nil_value();
511 return mrb_fixnum_value(tm->datetime.tm_mday);
512}
513
514
515/* 15.2.19.7.7 */
516/* Returns true if daylight saving was applied for this time. */
517static mrb_value
518mrb_time_dst_p(mrb_state *mrb, mrb_value self)
519{
520 struct mrb_time *tm;
521
522 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
523 return mrb_bool_value(tm->datetime.tm_isdst);
524}
525
526/* 15.2.19.7.8 */
527/* 15.2.19.7.10 */
528/* Returns the Time object of the UTC(GMT) timezone. */
529static mrb_value
530mrb_time_getutc(mrb_state *mrb, mrb_value self)
531{
532 struct mrb_time *tm, *tm2;
533
534 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
535 tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
536 *tm2 = *tm;
537 tm2->timezone = MRB_TIMEZONE_UTC;
538 mrb_time_update_datetime(tm2);
539 return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2);
540}
541
542/* 15.2.19.7.9 */
543/* Returns the Time object of the LOCAL timezone. */
544static mrb_value
545mrb_time_getlocal(mrb_state *mrb, mrb_value self)
546{
547 struct mrb_time *tm, *tm2;
548
549 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
550 tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
551 *tm2 = *tm;
552 tm2->timezone = MRB_TIMEZONE_LOCAL;
553 mrb_time_update_datetime(tm2);
554 return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2);
555}
556
557/* 15.2.19.7.15 */
558/* Returns hour of time. */
559static mrb_value
560mrb_time_hour(mrb_state *mrb, mrb_value self)
561{
562 struct mrb_time *tm;
563
564 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
565 return mrb_fixnum_value(tm->datetime.tm_hour);
566}
567
568/* 15.2.19.7.16 */
569/* Initializes a time by setting the amount of milliseconds since the epoch.*/
570static mrb_value
571mrb_time_initialize(mrb_state *mrb, mrb_value self)
572{
573 mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0,
574 amin = 0, asec = 0, ausec = 0;
575 int n;
576 struct mrb_time *tm;
577
578 tm = (struct mrb_time*)DATA_PTR(self);
579 if (tm) {
580 mrb_free(mrb, tm);
581 }
582 mrb_data_init(self, NULL, &mrb_time_type);
583
584 n = mrb_get_args(mrb, "|iiiiiii",
585 &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
586 if (n == 0) {
587 tm = current_mrb_time(mrb);
588 }
589 else {
590 tm = time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL);
591 }
592 mrb_data_init(self, tm, &mrb_time_type);
593 return self;
594}
595
596/* 15.2.19.7.17(x) */
597/* Initializes a copy of this time object. */
598static mrb_value
599mrb_time_initialize_copy(mrb_state *mrb, mrb_value copy)
600{
601 mrb_value src;
602
603 mrb_get_args(mrb, "o", &src);
604 if (mrb_obj_equal(mrb, copy, src)) return copy;
605 if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
606 mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
607 }
608 if (!DATA_PTR(copy)) {
609 mrb_data_init(copy, mrb_malloc(mrb, sizeof(struct mrb_time)), &mrb_time_type);
610 }
611 *(struct mrb_time *)DATA_PTR(copy) = *(struct mrb_time *)DATA_PTR(src);
612 return copy;
613}
614
615/* 15.2.19.7.18 */
616/* Sets the timezone attribute of the Time object to LOCAL. */
617static mrb_value
618mrb_time_localtime(mrb_state *mrb, mrb_value self)
619{
620 struct mrb_time *tm;
621
622 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
623 tm->timezone = MRB_TIMEZONE_LOCAL;
624 mrb_time_update_datetime(tm);
625 return self;
626}
627
628/* 15.2.19.7.19 */
629/* Returns day of month of time. */
630static mrb_value
631mrb_time_mday(mrb_state *mrb, mrb_value self)
632{
633 struct mrb_time *tm;
634
635 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
636 return mrb_fixnum_value(tm->datetime.tm_mday);
637}
638
639/* 15.2.19.7.20 */
640/* Returns minutes of time. */
641static mrb_value
642mrb_time_min(mrb_state *mrb, mrb_value self)
643{
644 struct mrb_time *tm;
645
646 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
647 return mrb_fixnum_value(tm->datetime.tm_min);
648}
649
650/* 15.2.19.7.21 and 15.2.19.7.22 */
651/* Returns month of time. */
652static mrb_value
653mrb_time_mon(mrb_state *mrb, mrb_value self)
654{
655 struct mrb_time *tm;
656
657 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
658 return mrb_fixnum_value(tm->datetime.tm_mon + 1);
659}
660
661/* 15.2.19.7.23 */
662/* Returns seconds in minute of time. */
663static mrb_value
664mrb_time_sec(mrb_state *mrb, mrb_value self)
665{
666 struct mrb_time *tm;
667
668 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
669 return mrb_fixnum_value(tm->datetime.tm_sec);
670}
671
672
673/* 15.2.19.7.24 */
674/* Returns a Float with the time since the epoch in seconds. */
675static mrb_value
676mrb_time_to_f(mrb_state *mrb, mrb_value self)
677{
678 struct mrb_time *tm;
679
680 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
681 return mrb_float_value(mrb, (mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6);
682}
683
684/* 15.2.19.7.25 */
685/* Returns a Fixnum with the time since the epoch in seconds. */
686static mrb_value
687mrb_time_to_i(mrb_state *mrb, mrb_value self)
688{
689 struct mrb_time *tm;
690
691 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
692 if (tm->sec > MRB_INT_MAX || tm->sec < MRB_INT_MIN) {
693 return mrb_float_value(mrb, (mrb_float)tm->sec);
694 }
695 return mrb_fixnum_value((mrb_int)tm->sec);
696}
697
698/* 15.2.19.7.26 */
699/* Returns a Float with the time since the epoch in microseconds. */
700static mrb_value
701mrb_time_usec(mrb_state *mrb, mrb_value self)
702{
703 struct mrb_time *tm;
704
705 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
706 if (tm->usec > MRB_INT_MAX || tm->usec < MRB_INT_MIN) {
707 return mrb_float_value(mrb, (mrb_float)tm->usec);
708 }
709 return mrb_fixnum_value((mrb_int)tm->usec);
710}
711
712/* 15.2.19.7.27 */
713/* Sets the timezone attribute of the Time object to UTC. */
714static mrb_value
715mrb_time_utc(mrb_state *mrb, mrb_value self)
716{
717 struct mrb_time *tm;
718
719 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
720 tm->timezone = MRB_TIMEZONE_UTC;
721 mrb_time_update_datetime(tm);
722 return self;
723}
724
725/* 15.2.19.7.28 */
726/* Returns true if this time is in the UTC timezone false if not. */
727static mrb_value
728mrb_time_utc_p(mrb_state *mrb, mrb_value self)
729{
730 struct mrb_time *tm;
731
732 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
733 return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC);
734}
735
736
737void
738mrb_mruby_time_gem_init(mrb_state* mrb)
739{
740 struct RClass *tc;
741 /* ISO 15.2.19.2 */
742 tc = mrb_define_class(mrb, "Time", mrb->object_class);
743 MRB_SET_INSTANCE_TT(tc, MRB_TT_DATA);
744 mrb_include_module(mrb, tc, mrb_module_get(mrb, "Comparable"));
745 mrb_define_class_method(mrb, tc, "at", mrb_time_at, MRB_ARGS_ARG(1, 1)); /* 15.2.19.6.1 */
746 mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.2 */
747 mrb_define_class_method(mrb, tc, "local", mrb_time_local, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.3 */
748 mrb_define_class_method(mrb, tc, "mktime", mrb_time_local, MRB_ARGS_ARG(1,6));/* 15.2.19.6.4 */
749 mrb_define_class_method(mrb, tc, "now", mrb_time_now, MRB_ARGS_NONE()); /* 15.2.19.6.5 */
750 mrb_define_class_method(mrb, tc, "utc", mrb_time_gm, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.6 */
751
752 mrb_define_method(mrb, tc, "==" , mrb_time_eq , MRB_ARGS_REQ(1));
753 mrb_define_method(mrb, tc, "<=>" , mrb_time_cmp , MRB_ARGS_REQ(1)); /* 15.2.19.7.1 */
754 mrb_define_method(mrb, tc, "+" , mrb_time_plus , MRB_ARGS_REQ(1)); /* 15.2.19.7.2 */
755 mrb_define_method(mrb, tc, "-" , mrb_time_minus , MRB_ARGS_REQ(1)); /* 15.2.19.7.3 */
756 mrb_define_method(mrb, tc, "to_s" , mrb_time_asctime, MRB_ARGS_NONE());
757 mrb_define_method(mrb, tc, "inspect", mrb_time_asctime, MRB_ARGS_NONE());
758 mrb_define_method(mrb, tc, "asctime", mrb_time_asctime, MRB_ARGS_NONE()); /* 15.2.19.7.4 */
759 mrb_define_method(mrb, tc, "ctime" , mrb_time_asctime, MRB_ARGS_NONE()); /* 15.2.19.7.5 */
760 mrb_define_method(mrb, tc, "day" , mrb_time_day , MRB_ARGS_NONE()); /* 15.2.19.7.6 */
761 mrb_define_method(mrb, tc, "dst?" , mrb_time_dst_p , MRB_ARGS_NONE()); /* 15.2.19.7.7 */
762 mrb_define_method(mrb, tc, "getgm" , mrb_time_getutc , MRB_ARGS_NONE()); /* 15.2.19.7.8 */
763 mrb_define_method(mrb, tc, "getlocal",mrb_time_getlocal,MRB_ARGS_NONE()); /* 15.2.19.7.9 */
764 mrb_define_method(mrb, tc, "getutc" , mrb_time_getutc , MRB_ARGS_NONE()); /* 15.2.19.7.10 */
765 mrb_define_method(mrb, tc, "gmt?" , mrb_time_utc_p , MRB_ARGS_NONE()); /* 15.2.19.7.11 */
766 mrb_define_method(mrb, tc, "gmtime" , mrb_time_utc , MRB_ARGS_NONE()); /* 15.2.19.7.13 */
767 mrb_define_method(mrb, tc, "hour" , mrb_time_hour, MRB_ARGS_NONE()); /* 15.2.19.7.15 */
768 mrb_define_method(mrb, tc, "localtime", mrb_time_localtime, MRB_ARGS_NONE()); /* 15.2.19.7.18 */
769 mrb_define_method(mrb, tc, "mday" , mrb_time_mday, MRB_ARGS_NONE()); /* 15.2.19.7.19 */
770 mrb_define_method(mrb, tc, "min" , mrb_time_min, MRB_ARGS_NONE()); /* 15.2.19.7.20 */
771
772 mrb_define_method(mrb, tc, "mon" , mrb_time_mon, MRB_ARGS_NONE()); /* 15.2.19.7.21 */
773 mrb_define_method(mrb, tc, "month", mrb_time_mon, MRB_ARGS_NONE()); /* 15.2.19.7.22 */
774
775 mrb_define_method(mrb, tc, "sec" , mrb_time_sec, MRB_ARGS_NONE()); /* 15.2.19.7.23 */
776 mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, MRB_ARGS_NONE()); /* 15.2.19.7.25 */
777 mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, MRB_ARGS_NONE()); /* 15.2.19.7.24 */
778 mrb_define_method(mrb, tc, "usec", mrb_time_usec, MRB_ARGS_NONE()); /* 15.2.19.7.26 */
779 mrb_define_method(mrb, tc, "utc" , mrb_time_utc, MRB_ARGS_NONE()); /* 15.2.19.7.27 */
780 mrb_define_method(mrb, tc, "utc?", mrb_time_utc_p,MRB_ARGS_NONE()); /* 15.2.19.7.28 */
781 mrb_define_method(mrb, tc, "wday", mrb_time_wday, MRB_ARGS_NONE()); /* 15.2.19.7.30 */
782 mrb_define_method(mrb, tc, "yday", mrb_time_yday, MRB_ARGS_NONE()); /* 15.2.19.7.31 */
783 mrb_define_method(mrb, tc, "year", mrb_time_year, MRB_ARGS_NONE()); /* 15.2.19.7.32 */
784 mrb_define_method(mrb, tc, "zone", mrb_time_zone, MRB_ARGS_NONE()); /* 15.2.19.7.33 */
785
786 mrb_define_method(mrb, tc, "initialize", mrb_time_initialize, MRB_ARGS_REQ(1)); /* 15.2.19.7.16 */
787 mrb_define_method(mrb, tc, "initialize_copy", mrb_time_initialize_copy, MRB_ARGS_REQ(1)); /* 15.2.19.7.17 */
788
789 /*
790 methods not available:
791 gmt_offset(15.2.19.7.12)
792 gmtoff(15.2.19.7.14)
793 utc_offset(15.2.19.7.29)
794 */
795}
796
797void
798mrb_mruby_time_gem_final(mrb_state* mrb)
799{
800}
Note: See TracBrowser for help on using the repository browser.