home_run 0.9.0-x86-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +3 -0
- data/LICENSE +19 -0
- data/README.rdoc +314 -0
- data/Rakefile +135 -0
- data/bench/cpu_bench.rb +279 -0
- data/bench/dt_garbage_bench.rb +11 -0
- data/bench/dt_mem_bench.rb +14 -0
- data/bench/garbage_bench.rb +11 -0
- data/bench/mem_bench.rb +14 -0
- data/bin/home_run +91 -0
- data/default.mspec +12 -0
- data/ext/1.8/date_ext.so +0 -0
- data/ext/1.9/date_ext.so +0 -0
- data/ext/date.rb +7 -0
- data/ext/date/format.rb +842 -0
- data/ext/date_ext.c +4548 -0
- data/ext/date_parser.c +367 -0
- data/ext/date_parser.rl +134 -0
- data/ext/datetime.c +2804 -0
- data/ext/extconf.rb +6 -0
- data/spec/date/accessor_spec.rb +176 -0
- data/spec/date/add_month_spec.rb +26 -0
- data/spec/date/add_spec.rb +23 -0
- data/spec/date/boat_spec.rb +38 -0
- data/spec/date/civil_spec.rb +147 -0
- data/spec/date/commercial_spec.rb +153 -0
- data/spec/date/constants_spec.rb +44 -0
- data/spec/date/conversions_spec.rb +246 -0
- data/spec/date/day_spec.rb +73 -0
- data/spec/date/downto_spec.rb +17 -0
- data/spec/date/eql_spec.rb +16 -0
- data/spec/date/format_spec.rb +52 -0
- data/spec/date/gregorian_spec.rb +52 -0
- data/spec/date/hash_spec.rb +11 -0
- data/spec/date/julian_spec.rb +129 -0
- data/spec/date/leap_spec.rb +19 -0
- data/spec/date/minus_month_spec.rb +25 -0
- data/spec/date/minus_spec.rb +51 -0
- data/spec/date/next_prev_spec.rb +108 -0
- data/spec/date/ordinal_spec.rb +83 -0
- data/spec/date/parse_spec.rb +442 -0
- data/spec/date/parsing_spec.rb +77 -0
- data/spec/date/relationship_spec.rb +28 -0
- data/spec/date/step_spec.rb +109 -0
- data/spec/date/strftime_spec.rb +223 -0
- data/spec/date/strptime_spec.rb +201 -0
- data/spec/date/succ_spec.rb +20 -0
- data/spec/date/today_spec.rb +15 -0
- data/spec/date/upto_spec.rb +17 -0
- data/spec/datetime/accessor_spec.rb +218 -0
- data/spec/datetime/add_month_spec.rb +26 -0
- data/spec/datetime/add_spec.rb +36 -0
- data/spec/datetime/boat_spec.rb +43 -0
- data/spec/datetime/constructor_spec.rb +142 -0
- data/spec/datetime/conversions_spec.rb +54 -0
- data/spec/datetime/day_spec.rb +73 -0
- data/spec/datetime/downto_spec.rb +39 -0
- data/spec/datetime/eql_spec.rb +17 -0
- data/spec/datetime/format_spec.rb +59 -0
- data/spec/datetime/hash_spec.rb +11 -0
- data/spec/datetime/leap_spec.rb +19 -0
- data/spec/datetime/minus_month_spec.rb +25 -0
- data/spec/datetime/minus_spec.rb +77 -0
- data/spec/datetime/next_prev_spec.rb +138 -0
- data/spec/datetime/now_spec.rb +18 -0
- data/spec/datetime/parse_spec.rb +390 -0
- data/spec/datetime/parsing_spec.rb +77 -0
- data/spec/datetime/relationship_spec.rb +28 -0
- data/spec/datetime/step_spec.rb +155 -0
- data/spec/datetime/strftime_spec.rb +118 -0
- data/spec/datetime/strptime_spec.rb +117 -0
- data/spec/datetime/succ_spec.rb +24 -0
- data/spec/datetime/upto_spec.rb +39 -0
- data/spec/spec_helper.rb +59 -0
- metadata +154 -0
data/ext/datetime.c
ADDED
@@ -0,0 +1,2804 @@
|
|
1
|
+
|
2
|
+
/* Helper methods */
|
3
|
+
|
4
|
+
/* Identical for rhrd__valid_civil, but for rhrdt_t. Not very
|
5
|
+
* DRY, but the arguments get modified by the method and then
|
6
|
+
* used to populate the rhrdt_t. Because the rhrd_t field structure
|
7
|
+
* has a different layout from the rhrdt_t field structure, you
|
8
|
+
* need separate functions (no duck typing in C). */
|
9
|
+
int rhrdt__valid_civil(rhrdt_t *dt, long year, long month, long day) {
|
10
|
+
if (month < 0 && month >= -12) {
|
11
|
+
month += 13;
|
12
|
+
}
|
13
|
+
if (month < 1 || month > 12) {
|
14
|
+
return 0;
|
15
|
+
}
|
16
|
+
|
17
|
+
if (day < 0) {
|
18
|
+
if (month == 2) {
|
19
|
+
day += rhrd__leap_year(year) ? 30 : 29;
|
20
|
+
} else {
|
21
|
+
day += rhrd_days_in_month[month] + 1;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
if (day < 1 || day > 28) {
|
25
|
+
if (day > 31 || day <= 0) {
|
26
|
+
return 0;
|
27
|
+
} else if (month == 2) {
|
28
|
+
if (rhrd__leap_year(year)) {
|
29
|
+
if (day > 29) {
|
30
|
+
return 0;
|
31
|
+
}
|
32
|
+
} else if (day > 28) {
|
33
|
+
return 0;
|
34
|
+
}
|
35
|
+
} else if (day > rhrd_days_in_month[month]) {
|
36
|
+
return 0;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
if(!rhrd__valid_civil_limits(year, month, day)) {
|
41
|
+
return 0;
|
42
|
+
}
|
43
|
+
|
44
|
+
dt->year = year;
|
45
|
+
dt->month = (unsigned char)month;
|
46
|
+
dt->day = (unsigned char)day;
|
47
|
+
dt->flags |= RHR_HAVE_CIVIL;
|
48
|
+
return 1;
|
49
|
+
}
|
50
|
+
|
51
|
+
/* Check if the given offset is valid. If so, set the offset field
|
52
|
+
* in the rhrdt_t and return 1. Otherwise, return 0. */
|
53
|
+
int rhrdt__valid_offset(rhrdt_t *dt, double offset) {
|
54
|
+
if (offset < RHR_MIN_OFFSET_FRACT || offset > RHR_MAX_OFFSET_FRACT) {
|
55
|
+
return 0;
|
56
|
+
}
|
57
|
+
|
58
|
+
dt->offset = lround(offset * 1440);
|
59
|
+
return 1;
|
60
|
+
}
|
61
|
+
|
62
|
+
/* Check if the time information consistutes a valid time. If not, return
|
63
|
+
* 0. If so, fill in the fields in the rhrdt_t and return 1. This handles
|
64
|
+
* wrap around for negative hour, minute, and second arguments, and handles
|
65
|
+
* an hour of 24 with no minute or second value as the 0th hour of the next
|
66
|
+
* day, so either the julian day or civil day fields in the rhrdt_t should
|
67
|
+
* be filled out before calling this method. */
|
68
|
+
int rhrdt__valid_time(rhrdt_t *dt, long h, long m, long s, double offset) {
|
69
|
+
if (h < 0) {
|
70
|
+
h += 24;
|
71
|
+
}
|
72
|
+
if (m < 0) {
|
73
|
+
m += 60;
|
74
|
+
}
|
75
|
+
if (s < 0) {
|
76
|
+
s += 60;
|
77
|
+
}
|
78
|
+
|
79
|
+
if (h == 24 && m == 0 && s == 0) {
|
80
|
+
RHRDT_FILL_JD(dt)
|
81
|
+
dt->jd++;
|
82
|
+
dt->flags &= ~RHR_HAVE_CIVIL;
|
83
|
+
h = 0;
|
84
|
+
} else if (h < 0 || m < 0 || s < 0 || h > 23 || m > 59 || s > 59) {
|
85
|
+
return 0;
|
86
|
+
}
|
87
|
+
if(!rhrdt__valid_offset(dt, offset)) {
|
88
|
+
return 0;
|
89
|
+
}
|
90
|
+
|
91
|
+
dt->hour = h;
|
92
|
+
dt->minute = m;
|
93
|
+
dt->second = s;
|
94
|
+
dt->flags |= RHR_HAVE_HMS;
|
95
|
+
return 1;
|
96
|
+
}
|
97
|
+
|
98
|
+
/* Same as rhrd__civil_to_jd for rhrdt_t. */
|
99
|
+
void rhrdt__civil_to_jd(rhrdt_t *d) {
|
100
|
+
d->jd = rhrd__ymd_to_jd(d->year, d->month, d->day);
|
101
|
+
d->flags |= RHR_HAVE_JD;
|
102
|
+
}
|
103
|
+
|
104
|
+
/* Same as rhrd__jd_to_civil for rhrdt_t. */
|
105
|
+
void rhrdt__jd_to_civil(rhrdt_t *date) {
|
106
|
+
long x, a, b, c, d, e;
|
107
|
+
x = (long)floor((date->jd - 1867216.25) / 36524.25);
|
108
|
+
a = date->jd + 1 + x - (long)floor(x / 4.0);
|
109
|
+
b = a + 1524;
|
110
|
+
c = (long)floor((b - 122.1) / 365.25);
|
111
|
+
d = (long)floor(365.25 * c);
|
112
|
+
e = (long)floor((b - d) / 30.6001);
|
113
|
+
date->day = b - d - (long)floor(30.6001 * e);
|
114
|
+
if (e <= 13) {
|
115
|
+
date->month = e - 1;
|
116
|
+
date->year = c - 4716;
|
117
|
+
} else {
|
118
|
+
date->month = e - 13;
|
119
|
+
date->year = c - 4715;
|
120
|
+
}
|
121
|
+
date->flags |= RHR_HAVE_CIVIL;
|
122
|
+
}
|
123
|
+
|
124
|
+
/* Using the stored nanos field, fill in the hour, minute,
|
125
|
+
* and second fields for the rhrdt_t. This assumes the
|
126
|
+
* nanos field has already been filled in. */
|
127
|
+
void rhrdt__nanos_to_hms(rhrdt_t *d) {
|
128
|
+
unsigned int seconds;
|
129
|
+
seconds = d->nanos/RHR_NANOS_PER_SECOND;
|
130
|
+
d->hour = seconds/RHR_SECONDS_PER_HOUR;
|
131
|
+
d->minute = (seconds % RHR_SECONDS_PER_HOUR)/60;
|
132
|
+
d->second = seconds % 60;
|
133
|
+
d->flags |= RHR_HAVE_HMS;
|
134
|
+
}
|
135
|
+
|
136
|
+
/* Using the stored hour, minute, and second fields, fill in
|
137
|
+
* the nanos field for th rhrdt_t. This assumes the hour, minute
|
138
|
+
* and second fields have already been filled in. */
|
139
|
+
void rhrdt__hms_to_nanos(rhrdt_t *d) {
|
140
|
+
d->nanos = (d->hour*RHR_SECONDS_PER_HOUR + d->minute*60 + d->second)*RHR_NANOS_PER_SECOND;
|
141
|
+
d->flags |= RHR_HAVE_NANOS;
|
142
|
+
}
|
143
|
+
|
144
|
+
/* Same as rhrd__valid_commercial, for rhrdt_t. */
|
145
|
+
int rhrdt__valid_commercial(rhrdt_t *d, long cwyear, long cweek, long cwday) {
|
146
|
+
rhrd_t n;
|
147
|
+
memset(&n, 0, sizeof(rhrd_t));
|
148
|
+
|
149
|
+
if (cwday < 0) {
|
150
|
+
if (cwday < -8) {
|
151
|
+
return 0;
|
152
|
+
}
|
153
|
+
cwday += 8;
|
154
|
+
}
|
155
|
+
if (cweek < 0) {
|
156
|
+
if (cweek < -53) {
|
157
|
+
return 0;
|
158
|
+
}
|
159
|
+
n.jd = rhrd__commercial_to_jd(cwyear + 1, 1, 1) + cweek * 7;
|
160
|
+
rhrd__fill_commercial(&n);
|
161
|
+
if (n.year != cwyear) {
|
162
|
+
return 0;
|
163
|
+
}
|
164
|
+
cweek = n.month;
|
165
|
+
memset(&n, 0, sizeof(rhrd_t));
|
166
|
+
}
|
167
|
+
|
168
|
+
n.jd = rhrd__commercial_to_jd(cwyear, cweek, cwday);
|
169
|
+
rhrd__fill_commercial(&n);
|
170
|
+
if(cwyear != n.year || cweek != n.month || cwday != n.day) {
|
171
|
+
return 0;
|
172
|
+
}
|
173
|
+
|
174
|
+
if ((n.jd > RHR_JD_MAX) || (n.jd < RHR_JD_MIN)) {
|
175
|
+
return 0;
|
176
|
+
}
|
177
|
+
|
178
|
+
d->jd = n.jd;
|
179
|
+
d->flags = RHR_HAVE_JD;
|
180
|
+
return 1;
|
181
|
+
}
|
182
|
+
|
183
|
+
/* Same as rhrd__valid_ordinal, for rhrdt_t. */
|
184
|
+
int rhrdt__valid_ordinal(rhrdt_t *d, long year, long yday) {
|
185
|
+
int leap;
|
186
|
+
long month, day;
|
187
|
+
|
188
|
+
leap = rhrd__leap_year(year);
|
189
|
+
if (yday < 0) {
|
190
|
+
if (leap) {
|
191
|
+
yday += 367;
|
192
|
+
} else {
|
193
|
+
yday += 366;
|
194
|
+
}
|
195
|
+
}
|
196
|
+
if (yday < 1 || yday > (leap ? 366 : 365)) {
|
197
|
+
return 0;
|
198
|
+
}
|
199
|
+
if (leap) {
|
200
|
+
month = rhrd_leap_yday_to_month[yday];
|
201
|
+
if (yday > 60) {
|
202
|
+
day = yday - rhrd_cumulative_days_in_month[month] - 1;
|
203
|
+
} else {
|
204
|
+
day = yday - rhrd_cumulative_days_in_month[month];
|
205
|
+
}
|
206
|
+
} else {
|
207
|
+
month = rhrd_yday_to_month[yday];
|
208
|
+
day = yday - rhrd_cumulative_days_in_month[month];
|
209
|
+
}
|
210
|
+
|
211
|
+
if(!rhrd__valid_civil_limits(year, month, day)) {
|
212
|
+
return 0;
|
213
|
+
}
|
214
|
+
|
215
|
+
d->year = year;
|
216
|
+
d->month = (unsigned char)month;
|
217
|
+
d->day = (unsigned char)day;
|
218
|
+
d->flags |= RHR_HAVE_CIVIL;
|
219
|
+
return 1;
|
220
|
+
}
|
221
|
+
|
222
|
+
/* Fill the rhrdt_t with the current time information. On
|
223
|
+
* ruby 1.9, this is accurate to nanoseconds if the platform
|
224
|
+
* supports it, while on ruby 1.8 is is accurate to microseconds.
|
225
|
+
* On Windows, it's only accurate to within about 15 milliseconds. */
|
226
|
+
void rhrdt__now(rhrdt_t * dt) {
|
227
|
+
long t;
|
228
|
+
long offset;
|
229
|
+
VALUE rt;
|
230
|
+
rt = rb_funcall(rb_cTime, rhrd_id_now, 0);
|
231
|
+
offset = NUM2LONG(rb_funcall(rt, rhrd_id_utc_offset, 0));
|
232
|
+
t = NUM2LONG(rb_funcall(rt, rhrd_id_to_i, 0)) + offset;
|
233
|
+
dt->jd = rhrd__unix_to_jd(t);
|
234
|
+
#ifdef RUBY19
|
235
|
+
dt->nanos = rhrd__mod(t, RHR_SECONDS_PER_DAY) * RHR_NANOS_PER_SECOND + NUM2LONG(rb_funcall(rt, rhrd_id_nsec, 0));
|
236
|
+
#else
|
237
|
+
dt->nanos = rhrd__mod(t, RHR_SECONDS_PER_DAY) * RHR_NANOS_PER_SECOND + NUM2LONG(rb_funcall(rt, rhrd_id_usec, 0)) * 1000;
|
238
|
+
#endif
|
239
|
+
dt->offset = offset/60;
|
240
|
+
dt->flags |= RHR_HAVE_JD | RHR_HAVE_NANOS;
|
241
|
+
RHR_CHECK_JD(dt);
|
242
|
+
}
|
243
|
+
|
244
|
+
/* Return a new ruby DateTime object using the given jd, nanos,
|
245
|
+
* and offset. The offset should already be in minutes-from-UTC
|
246
|
+
* format. This handles negative nanos or nanos greater than
|
247
|
+
* the number per day by subtracting from or adding to the jd.
|
248
|
+
* It should ensure that the stored nanos value is in the range
|
249
|
+
* [0, RHR_NANOS_PER_DAY). */
|
250
|
+
VALUE rhrdt__from_jd_nanos(long jd, long long nanos, short offset) {
|
251
|
+
long t;
|
252
|
+
rhrdt_t *dt;
|
253
|
+
VALUE new;
|
254
|
+
new = Data_Make_Struct(rhrdt_class, rhrdt_t, NULL, free, dt);
|
255
|
+
|
256
|
+
if (nanos < 0) {
|
257
|
+
t = nanos/RHR_NANOS_PER_DAY - 1;
|
258
|
+
nanos -= t * RHR_NANOS_PER_DAY;
|
259
|
+
jd += t;
|
260
|
+
} else if (nanos >= RHR_NANOS_PER_DAY) {
|
261
|
+
t = nanos/RHR_NANOS_PER_DAY;
|
262
|
+
nanos -= t * RHR_NANOS_PER_DAY;
|
263
|
+
jd += t;
|
264
|
+
}
|
265
|
+
dt->jd = jd;
|
266
|
+
dt->nanos = nanos;
|
267
|
+
dt->offset = offset;
|
268
|
+
dt->flags = RHR_HAVE_JD | RHR_HAVE_NANOS;
|
269
|
+
return new;
|
270
|
+
}
|
271
|
+
|
272
|
+
/* Similar to rhrd__spaceship. Unlike that, we
|
273
|
+
* don't try to speed up by checking which fields
|
274
|
+
* are already stored, we just fill the jd and
|
275
|
+
* nanos fields for both and compare them.*/
|
276
|
+
long rhrdt__spaceship(rhrdt_t *dt, rhrdt_t *odt) {
|
277
|
+
RHRDT_FILL_JD(dt)
|
278
|
+
RHRDT_FILL_JD(odt)
|
279
|
+
RHRDT_FILL_NANOS(dt)
|
280
|
+
RHRDT_FILL_NANOS(odt)
|
281
|
+
if (dt->jd == odt->jd) {
|
282
|
+
if (dt->nanos == odt->nanos) {
|
283
|
+
return 0;
|
284
|
+
} else if (dt->nanos < odt->nanos) {
|
285
|
+
return -1;
|
286
|
+
}
|
287
|
+
return 1;
|
288
|
+
} else if (dt->jd < odt->jd) {
|
289
|
+
return -1;
|
290
|
+
}
|
291
|
+
return 1;
|
292
|
+
}
|
293
|
+
|
294
|
+
/* Similar to rhrd__add_days, but n is a double in
|
295
|
+
* order to handle fractional days. */
|
296
|
+
VALUE rhrdt__add_days(VALUE self, double n) {
|
297
|
+
long l;
|
298
|
+
long long nanos;
|
299
|
+
rhrdt_t *dt;
|
300
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
301
|
+
RHRDT_FILL_JD(dt)
|
302
|
+
RHRDT_FILL_NANOS(dt)
|
303
|
+
l = floor(n);
|
304
|
+
nanos = llround((n - l) * RHR_NANOS_PER_DAY);
|
305
|
+
return rhrdt__from_jd_nanos(rhrd__safe_add_long(dt->jd, l), dt->nanos + nanos, dt->offset);
|
306
|
+
}
|
307
|
+
|
308
|
+
/* Similar to rhrd__add_months, but for ruby DateTime
|
309
|
+
* values. */
|
310
|
+
VALUE rhrdt__add_months(VALUE self, long n) {
|
311
|
+
rhrdt_t *d;
|
312
|
+
rhrdt_t *newd;
|
313
|
+
VALUE new;
|
314
|
+
long x;
|
315
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
316
|
+
|
317
|
+
new = Data_Make_Struct(rhrdt_class, rhrdt_t, NULL, free, newd);
|
318
|
+
RHRDT_FILL_CIVIL(d)
|
319
|
+
memcpy(newd, d, sizeof(rhrdt_t));
|
320
|
+
|
321
|
+
n = rhrd__safe_add_long(n, (long)(d->month));
|
322
|
+
if(n > 1 && n <= 12) {
|
323
|
+
newd->year = d->year;
|
324
|
+
newd->month = n;
|
325
|
+
} else {
|
326
|
+
x = n / 12;
|
327
|
+
n = n % 12;
|
328
|
+
if (n <= 0) {
|
329
|
+
newd->year = d->year + x - 1;
|
330
|
+
newd->month = n + 12;
|
331
|
+
} else {
|
332
|
+
newd->year = d->year + x;
|
333
|
+
newd->month = (unsigned char)n;
|
334
|
+
}
|
335
|
+
}
|
336
|
+
x = rhrd__days_in_month(newd->year, newd->month);
|
337
|
+
newd->day = (unsigned char)(d->day > x ? x : d->day);
|
338
|
+
RHR_CHECK_CIVIL(newd)
|
339
|
+
newd->flags &= ~RHR_HAVE_JD;
|
340
|
+
return new;
|
341
|
+
}
|
342
|
+
|
343
|
+
/* Similar to rhrd__fill_from_hash for rhrdt_t, except instead of
|
344
|
+
* returning 1 or 0, this raises ruby ArgumentErrors. */
|
345
|
+
void rhrdt__fill_from_hash(rhrdt_t *dt, VALUE hash) {
|
346
|
+
rhrd_t d;
|
347
|
+
long hour = 0;
|
348
|
+
long minute = 0;
|
349
|
+
long second = 0;
|
350
|
+
long offset = 0;
|
351
|
+
long long nanos = 0;
|
352
|
+
long long time_set = 0;
|
353
|
+
int r;
|
354
|
+
VALUE rhour, rmin, rsec, runix, roffset, rsecf;
|
355
|
+
|
356
|
+
if (!RTEST(hash)) {
|
357
|
+
rb_raise(rb_eArgError, "invalid date");
|
358
|
+
}
|
359
|
+
|
360
|
+
roffset = rb_hash_aref(hash, rhrd_sym_offset);
|
361
|
+
if (RTEST(roffset)) {
|
362
|
+
offset = NUM2LONG(roffset);
|
363
|
+
}
|
364
|
+
|
365
|
+
rsecf = rb_hash_aref(hash, rhrd_sym_sec_fraction);
|
366
|
+
if (RTEST(rsecf)) {
|
367
|
+
nanos = llround(NUM2DBL(rsecf) * RHR_NANOS_PER_SECOND);
|
368
|
+
}
|
369
|
+
|
370
|
+
runix = rb_hash_aref(hash, rhrd_sym_seconds);
|
371
|
+
if (RTEST(runix)) {
|
372
|
+
time_set = NUM2LL(runix);
|
373
|
+
dt->jd = rhrd__unix_to_jd(time_set);
|
374
|
+
time_set = rhrd__modll(time_set, RHR_SECONDS_PER_DAY);
|
375
|
+
dt->nanos = time_set*RHR_NANOS_PER_SECOND + nanos;
|
376
|
+
dt->hour = time_set/RHR_SECONDS_PER_HOUR;
|
377
|
+
dt->minute = (time_set - dt->hour * RHR_SECONDS_PER_HOUR)/60;
|
378
|
+
dt->second = rhrd__mod(time_set, 60);
|
379
|
+
offset /= 60;
|
380
|
+
if (offset > RHR_MAX_OFFSET_MINUTES || offset < RHR_MIN_OFFSET_MINUTES) {
|
381
|
+
rb_raise(rb_eArgError, "invalid offset: %ld minutes", offset);
|
382
|
+
}
|
383
|
+
RHR_CHECK_JD(dt);
|
384
|
+
dt->flags = RHR_HAVE_JD | RHR_HAVE_NANOS | RHR_HAVE_HMS;
|
385
|
+
return;
|
386
|
+
} else {
|
387
|
+
rhour = rb_hash_aref(hash, rhrd_sym_hour);
|
388
|
+
rmin = rb_hash_aref(hash, rhrd_sym_min);
|
389
|
+
rsec = rb_hash_aref(hash, rhrd_sym_sec);
|
390
|
+
|
391
|
+
if (RTEST(rhour)) {
|
392
|
+
time_set = 1;
|
393
|
+
hour = NUM2LONG(rhour);
|
394
|
+
}
|
395
|
+
if (RTEST(rmin)) {
|
396
|
+
time_set = 1;
|
397
|
+
minute = NUM2LONG(rmin);
|
398
|
+
}
|
399
|
+
if (RTEST(rsec)) {
|
400
|
+
time_set = 1;
|
401
|
+
second = NUM2LONG(rsec);
|
402
|
+
}
|
403
|
+
}
|
404
|
+
|
405
|
+
memset(&d, 0, sizeof(rhrd_t));
|
406
|
+
r = rhrd__fill_from_hash(&d, hash);
|
407
|
+
if(r > 0) {
|
408
|
+
/* bad date info */
|
409
|
+
rb_raise(rb_eArgError, "invalid date");
|
410
|
+
} else if (r < 0) {
|
411
|
+
if (time_set) {
|
412
|
+
/* time info but no date info, assume current date */
|
413
|
+
rhrd__today(&d);
|
414
|
+
} else {
|
415
|
+
/* no time or date info */
|
416
|
+
rb_raise(rb_eArgError, "invalid date");
|
417
|
+
}
|
418
|
+
}
|
419
|
+
|
420
|
+
if(RHR_HAS_JD(&d)) {
|
421
|
+
dt->jd = d.jd;
|
422
|
+
dt->flags |= RHR_HAVE_JD;
|
423
|
+
}
|
424
|
+
if(RHR_HAS_CIVIL(&d)) {
|
425
|
+
dt->year = d.year;
|
426
|
+
dt->month = d.month;
|
427
|
+
dt->day = d.day;
|
428
|
+
dt->flags |= RHR_HAVE_CIVIL;
|
429
|
+
}
|
430
|
+
if(time_set) {
|
431
|
+
rhrdt__valid_time(dt, hour, minute, second, offset/RHR_SECONDS_PER_DAYD);
|
432
|
+
if(nanos) {
|
433
|
+
RHRDT_FILL_NANOS(dt)
|
434
|
+
dt->nanos += nanos;
|
435
|
+
}
|
436
|
+
} else if (offset) {
|
437
|
+
if(!rhrdt__valid_offset(dt, offset/RHR_SECONDS_PER_DAYD)){
|
438
|
+
rb_raise(rb_eArgError, "invalid date");
|
439
|
+
}
|
440
|
+
}
|
441
|
+
}
|
442
|
+
|
443
|
+
/* Return a new ruby DateTime object with the same
|
444
|
+
* absolute time as the given one, but with a different
|
445
|
+
* offset. */
|
446
|
+
VALUE rhrdt__new_offset(VALUE self, double offset) {
|
447
|
+
rhrdt_t *dt;
|
448
|
+
long offset_min;
|
449
|
+
|
450
|
+
if(offset < RHR_MIN_OFFSET_FRACT || offset > RHR_MAX_OFFSET_FRACT) {
|
451
|
+
rb_raise(rb_eArgError, "invalid offset (%f)", offset);
|
452
|
+
}
|
453
|
+
offset_min = lround(offset * 1440.0);
|
454
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
455
|
+
RHRDT_FILL_JD(dt)
|
456
|
+
RHRDT_FILL_NANOS(dt)
|
457
|
+
return rhrdt__from_jd_nanos(dt->jd, dt->nanos - (dt->offset - offset_min)*RHR_NANOS_PER_MINUTE, offset_min);
|
458
|
+
}
|
459
|
+
|
460
|
+
/* Class methods */
|
461
|
+
|
462
|
+
/* call-seq:
|
463
|
+
* _load(string) -> DateTime
|
464
|
+
*
|
465
|
+
* Unmarshal a dumped +DateTime+ object. Not generally called directly,
|
466
|
+
* usually called by <tt>Marshal.load</tt>.
|
467
|
+
*
|
468
|
+
* Note that this does not handle the marshalling format used by
|
469
|
+
* the stdlib's +DateTime+, it only handles marshalled versions of
|
470
|
+
* this library's +DateTime+ objects.
|
471
|
+
*/
|
472
|
+
static VALUE rhrdt_s__load(VALUE klass, VALUE string) {
|
473
|
+
rhrdt_t * d;
|
474
|
+
long x;
|
475
|
+
VALUE ary, rd;
|
476
|
+
rd = Data_Make_Struct(klass, rhrdt_t, NULL, free, d);
|
477
|
+
|
478
|
+
ary = rb_marshal_load(string);
|
479
|
+
if (!RTEST(rb_obj_is_kind_of(ary, rb_cArray)) || RARRAY_LEN(ary) != 3) {
|
480
|
+
rb_raise(rb_eTypeError, "incompatible marshal file format");
|
481
|
+
}
|
482
|
+
|
483
|
+
d->jd = NUM2LONG(rb_ary_entry(ary, 0));
|
484
|
+
RHR_CHECK_JD(d)
|
485
|
+
|
486
|
+
d->nanos = NUM2LL(rb_ary_entry(ary, 1));
|
487
|
+
if (d->nanos < 0 || d->nanos >= RHR_NANOS_PER_DAY) {
|
488
|
+
rb_raise(rb_eArgError, "invalid nanos: %lld", d->nanos);
|
489
|
+
}
|
490
|
+
|
491
|
+
x = NUM2LONG(rb_ary_entry(ary, 2));
|
492
|
+
if (x > RHR_MAX_OFFSET_MINUTES || x < RHR_MIN_OFFSET_MINUTES) {
|
493
|
+
rb_raise(rb_eArgError, "invalid offset: %ld minutes", x);
|
494
|
+
}
|
495
|
+
d->offset = x;
|
496
|
+
|
497
|
+
d->flags = RHR_HAVE_JD | RHR_HAVE_NANOS;
|
498
|
+
return rd;
|
499
|
+
}
|
500
|
+
|
501
|
+
/* call-seq:
|
502
|
+
* _strptime(string, format='%FT%T%z') -> Hash or nil
|
503
|
+
*
|
504
|
+
* Attemps to parse the string using the given format, returning
|
505
|
+
* a hash if there is a match (or +nil+ if no match).
|
506
|
+
*
|
507
|
+
* +_strptime+ supports the same formats that <tt>DateTime#strftime</tt> does.
|
508
|
+
*/
|
509
|
+
static VALUE rhrdt_s__strptime(int argc, VALUE *argv, VALUE klass) {
|
510
|
+
const char * fmt_str = "%FT%T%z";
|
511
|
+
long fmt_len = 7;
|
512
|
+
VALUE r;
|
513
|
+
|
514
|
+
switch(argc) {
|
515
|
+
case 2:
|
516
|
+
r = rb_str_to_str(argv[1]);
|
517
|
+
fmt_str = RSTRING_PTR(r);
|
518
|
+
fmt_len = RSTRING_LEN(r);
|
519
|
+
case 1:
|
520
|
+
break;
|
521
|
+
default:
|
522
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%i for 2)", argc);
|
523
|
+
break;
|
524
|
+
}
|
525
|
+
|
526
|
+
return rhrd__strptime(argv[0], fmt_str, fmt_len);
|
527
|
+
}
|
528
|
+
|
529
|
+
/* call-seq:
|
530
|
+
* civil() -> DateTime <br />
|
531
|
+
* civil(year, month=1, day=1, hour=0, minute=0, second=0, offset=0, sg=nil) -> DateTime
|
532
|
+
*
|
533
|
+
* If no arguments are given, returns a +DateTime+ for julian day 0.
|
534
|
+
* Otherwise, returns a +DateTime+ for the year, month, day, hour, minute, second
|
535
|
+
* and offset given.
|
536
|
+
* Raises an +ArgumentError+ for invalid dates or times.
|
537
|
+
* Ignores the 8th argument.
|
538
|
+
*/
|
539
|
+
static VALUE rhrdt_s_civil(int argc, VALUE *argv, VALUE klass) {
|
540
|
+
rhrdt_t *dt;
|
541
|
+
long year;
|
542
|
+
long month = 1;
|
543
|
+
long day = 1;
|
544
|
+
long hour = 0;
|
545
|
+
long minute = 0;
|
546
|
+
long second = 0;
|
547
|
+
double offset = 0.0;
|
548
|
+
VALUE rdt = Data_Make_Struct(klass, rhrdt_t, NULL, free, dt);
|
549
|
+
|
550
|
+
switch(argc) {
|
551
|
+
case 0:
|
552
|
+
dt->flags = RHR_HAVE_JD | RHR_HAVE_NANOS | RHR_HAVE_HMS;
|
553
|
+
return rdt;
|
554
|
+
case 8:
|
555
|
+
case 7:
|
556
|
+
offset = NUM2DBL(argv[6]);
|
557
|
+
case 6:
|
558
|
+
second = NUM2LONG(argv[5]);
|
559
|
+
case 5:
|
560
|
+
minute = NUM2LONG(argv[4]);
|
561
|
+
case 4:
|
562
|
+
hour = NUM2LONG(argv[3]);
|
563
|
+
case 3:
|
564
|
+
day = NUM2LONG(argv[2]);
|
565
|
+
case 2:
|
566
|
+
month = NUM2LONG(argv[1]);
|
567
|
+
case 1:
|
568
|
+
year = NUM2LONG(argv[0]);
|
569
|
+
break;
|
570
|
+
default:
|
571
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 8", argc);
|
572
|
+
break;
|
573
|
+
}
|
574
|
+
|
575
|
+
if (!rhrdt__valid_civil(dt, year, month, day)) {
|
576
|
+
RHR_CHECK_CIVIL(dt)
|
577
|
+
rb_raise(rb_eArgError, "invalid date (year: %li, month: %li, day: %li)", year, month, day);
|
578
|
+
}
|
579
|
+
if (!rhrdt__valid_time(dt, hour, minute, second, offset)) {
|
580
|
+
rb_raise(rb_eArgError, "invalid time (hour: %li, minute: %li, second: %li, offset: %f)", hour, minute, second, offset);
|
581
|
+
}
|
582
|
+
|
583
|
+
return rdt;
|
584
|
+
}
|
585
|
+
|
586
|
+
/* call-seq:
|
587
|
+
* commercial() -> DateTime <br />
|
588
|
+
* commercial(cwyear, cweek=41, cwday=5, hour=0, minute=0, second=0, offset=0, sg=nil) -> DateTime [ruby 1-8] <br />
|
589
|
+
* commercial(cwyear, cweek=1, cwday=1, hour=0, minute=0, second=0, offset=0, sg=nil) -> DateTime [ruby 1-9]
|
590
|
+
*
|
591
|
+
* If no arguments are given:
|
592
|
+
* * ruby 1.8: returns a +DateTime+ for 1582-10-15 (the Day of Calendar Reform in Italy)
|
593
|
+
* * ruby 1.9: returns a +DateTime+ for julian day 0
|
594
|
+
*
|
595
|
+
* Otherwise, returns a +DateTime+ for the commercial week year, commercial week,
|
596
|
+
* commercial week day, hour, minute, second, and offset given.
|
597
|
+
* Raises an +ArgumentError+ for invalid dates or times.
|
598
|
+
* Ignores the 8th argument.
|
599
|
+
*/
|
600
|
+
static VALUE rhrdt_s_commercial(int argc, VALUE *argv, VALUE klass) {
|
601
|
+
rhrdt_t *dt;
|
602
|
+
long cwyear = RHR_DEFAULT_CWYEAR;
|
603
|
+
long cweek = RHR_DEFAULT_CWEEK;
|
604
|
+
long cwday = RHR_DEFAULT_CWDAY;
|
605
|
+
long hour = 0;
|
606
|
+
long minute = 0;
|
607
|
+
long second = 0;
|
608
|
+
double offset = 0.0;
|
609
|
+
VALUE rdt = Data_Make_Struct(klass, rhrdt_t, NULL, free, dt);
|
610
|
+
|
611
|
+
switch(argc) {
|
612
|
+
case 8:
|
613
|
+
case 7:
|
614
|
+
offset = NUM2DBL(argv[6]);
|
615
|
+
case 6:
|
616
|
+
second = NUM2LONG(argv[5]);
|
617
|
+
case 5:
|
618
|
+
minute = NUM2LONG(argv[4]);
|
619
|
+
case 4:
|
620
|
+
hour = NUM2LONG(argv[3]);
|
621
|
+
case 3:
|
622
|
+
cwday = NUM2LONG(argv[2]);
|
623
|
+
case 2:
|
624
|
+
cweek = NUM2LONG(argv[1]);
|
625
|
+
case 1:
|
626
|
+
cwyear = NUM2LONG(argv[0]);
|
627
|
+
#ifdef RUBY19
|
628
|
+
break;
|
629
|
+
case 0:
|
630
|
+
dt->flags = RHR_HAVE_JD | RHR_HAVE_NANOS | RHR_HAVE_HMS;
|
631
|
+
return rdt;
|
632
|
+
#else
|
633
|
+
case 0:
|
634
|
+
break;
|
635
|
+
#endif
|
636
|
+
default:
|
637
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 8", argc);
|
638
|
+
break;
|
639
|
+
}
|
640
|
+
if(!rhrdt__valid_commercial(dt, cwyear, cweek, cwday)) {
|
641
|
+
RHR_CHECK_JD(dt)
|
642
|
+
rb_raise(rb_eArgError, "invalid date (cwyear: %li, cweek: %li, cwday: %li)", cwyear, cweek, cwday);
|
643
|
+
}
|
644
|
+
if (!rhrdt__valid_time(dt, hour, minute, second, offset)) {
|
645
|
+
rb_raise(rb_eArgError, "invalid time (hour: %li, minute: %li, second: %li, offset: %f)", hour, minute, second, offset);
|
646
|
+
}
|
647
|
+
|
648
|
+
return rdt;
|
649
|
+
}
|
650
|
+
|
651
|
+
/* call-seq:
|
652
|
+
* jd(jd=0, hour=0, minute=0, second=0, offset=0, sg=nil) -> DateTime
|
653
|
+
*
|
654
|
+
* Returns a +DateTime+ for the julian day number,
|
655
|
+
* hour, minute, second, and offset given.
|
656
|
+
* Raises +ArgumentError+ for invalid times.
|
657
|
+
* Ignores the 6th argument.
|
658
|
+
*/
|
659
|
+
static VALUE rhrdt_s_jd(int argc, VALUE *argv, VALUE klass) {
|
660
|
+
rhrdt_t *dt;
|
661
|
+
long hour = 0;
|
662
|
+
long minute = 0;
|
663
|
+
long second = 0;
|
664
|
+
double offset = 0.0;
|
665
|
+
VALUE rdt = Data_Make_Struct(klass, rhrdt_t, NULL, free, dt);
|
666
|
+
|
667
|
+
switch(argc) {
|
668
|
+
case 0:
|
669
|
+
dt->flags = RHR_HAVE_JD | RHR_HAVE_NANOS | RHR_HAVE_HMS;
|
670
|
+
return rdt;
|
671
|
+
case 6:
|
672
|
+
case 5:
|
673
|
+
offset = NUM2DBL(argv[4]);
|
674
|
+
case 4:
|
675
|
+
second = NUM2LONG(argv[3]);
|
676
|
+
case 3:
|
677
|
+
minute = NUM2LONG(argv[2]);
|
678
|
+
case 2:
|
679
|
+
hour = NUM2LONG(argv[1]);
|
680
|
+
case 1:
|
681
|
+
dt->jd = NUM2LONG(argv[0]);
|
682
|
+
break;
|
683
|
+
default:
|
684
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 6", argc);
|
685
|
+
break;
|
686
|
+
}
|
687
|
+
|
688
|
+
RHR_CHECK_JD(dt)
|
689
|
+
dt->flags = RHR_HAVE_JD;
|
690
|
+
if (!rhrdt__valid_time(dt, hour, minute, second, offset)) {
|
691
|
+
rb_raise(rb_eArgError, "invalid time (hour: %li, minute: %li, second: %li, offset: %f)", hour, minute, second, offset);
|
692
|
+
}
|
693
|
+
|
694
|
+
return rdt;
|
695
|
+
}
|
696
|
+
|
697
|
+
/* call-seq:
|
698
|
+
* new!(ajd=0, offset=0, sg=nil) -> DateTime
|
699
|
+
*
|
700
|
+
* Returns a +DateTime+ for the astronomical julian day number and offset given.
|
701
|
+
* To include a fractional day, +ajd+ can be a +Float+. The date is assumed
|
702
|
+
* to be based at noon UTC, so if +ajd+ is an +Integer+ and +offset+ is 0,
|
703
|
+
* the hour will be 12.
|
704
|
+
* Ignores the 3rd argument. Example:
|
705
|
+
*
|
706
|
+
* DateTime.new!(2422222).to_s
|
707
|
+
* # => "1919-09-20T12:00:00+00:00"
|
708
|
+
* DateTime.new!(2422222.5).to_s
|
709
|
+
* # => "1919-09-21T00:00:00+00:00"
|
710
|
+
* DateTime.new!(2422222, 0.5).to_s
|
711
|
+
* # => "1919-09-21T00:00:00+12:00"
|
712
|
+
* DateTime.new!(2422222.5, 0.5).to_s
|
713
|
+
* # => "1919-09-21T12:00:00+12:00"
|
714
|
+
*/
|
715
|
+
static VALUE rhrdt_s_new_b(int argc, VALUE *argv, VALUE klass) {
|
716
|
+
double offset = 0;
|
717
|
+
rhrdt_t *dt;
|
718
|
+
VALUE rdt = Data_Make_Struct(klass, rhrdt_t, NULL, free, dt);
|
719
|
+
|
720
|
+
switch(argc) {
|
721
|
+
case 0:
|
722
|
+
dt->flags = RHR_HAVE_JD | RHR_HAVE_NANOS | RHR_HAVE_HMS;
|
723
|
+
return rdt;
|
724
|
+
case 2:
|
725
|
+
case 3:
|
726
|
+
offset = NUM2DBL(argv[1]);
|
727
|
+
if (!rhrdt__valid_offset(dt, offset)) {
|
728
|
+
rb_raise(rb_eArgError, "invalid offset (%f)", offset);
|
729
|
+
}
|
730
|
+
case 1:
|
731
|
+
offset += NUM2DBL(argv[0]) + 0.5;
|
732
|
+
dt->jd = offset;
|
733
|
+
dt->nanos = (offset - dt->jd)*RHR_NANOS_PER_DAY;
|
734
|
+
dt->flags = RHR_HAVE_JD | RHR_HAVE_NANOS;
|
735
|
+
break;
|
736
|
+
default:
|
737
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 3", argc);
|
738
|
+
break;
|
739
|
+
}
|
740
|
+
|
741
|
+
RHR_CHECK_JD(dt)
|
742
|
+
return rdt;
|
743
|
+
}
|
744
|
+
|
745
|
+
/* call-seq:
|
746
|
+
* now(sg=nil) -> DateTime
|
747
|
+
*
|
748
|
+
* Returns a +DateTime+ representing the current local date
|
749
|
+
* and time.
|
750
|
+
* Ignores an argument if given.
|
751
|
+
*/
|
752
|
+
static VALUE rhrdt_s_now(int argc, VALUE *argv, VALUE klass) {
|
753
|
+
rhrdt_t *dt;
|
754
|
+
VALUE rdt = Data_Make_Struct(klass, rhrdt_t, NULL, free, dt);
|
755
|
+
|
756
|
+
switch(argc) {
|
757
|
+
case 0:
|
758
|
+
case 1:
|
759
|
+
break;
|
760
|
+
default:
|
761
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
762
|
+
break;
|
763
|
+
}
|
764
|
+
|
765
|
+
rhrdt__now(dt);
|
766
|
+
return rdt;
|
767
|
+
}
|
768
|
+
|
769
|
+
/* call-seq:
|
770
|
+
* ordinal() -> DateTime <br />
|
771
|
+
* ordinal(year, yday=1, hour=0, minute=0, second=0, offset=0, sg=nil) -> DateTime
|
772
|
+
*
|
773
|
+
* If no arguments are given, returns a +DateTime+ for julian day 0.
|
774
|
+
* Otherwise, returns a +DateTime+ for the year, day of year,
|
775
|
+
* hour, minute, second, and offset given.
|
776
|
+
* Raises an +ArgumentError+ for invalid dates.
|
777
|
+
* Ignores the 7th argument.
|
778
|
+
*/
|
779
|
+
static VALUE rhrdt_s_ordinal(int argc, VALUE *argv, VALUE klass) {
|
780
|
+
long year;
|
781
|
+
long day = 1;
|
782
|
+
long hour = 0;
|
783
|
+
long minute = 0;
|
784
|
+
long second = 0;
|
785
|
+
double offset = 0.0;
|
786
|
+
rhrdt_t *dt;
|
787
|
+
VALUE rdt = Data_Make_Struct(klass, rhrdt_t, NULL, free, dt);
|
788
|
+
|
789
|
+
switch(argc) {
|
790
|
+
case 7:
|
791
|
+
case 6:
|
792
|
+
offset = NUM2DBL(argv[5]);
|
793
|
+
case 5:
|
794
|
+
second = NUM2LONG(argv[4]);
|
795
|
+
case 4:
|
796
|
+
minute = NUM2LONG(argv[3]);
|
797
|
+
case 3:
|
798
|
+
hour = NUM2LONG(argv[2]);
|
799
|
+
case 2:
|
800
|
+
day = NUM2LONG(argv[1]);
|
801
|
+
case 1:
|
802
|
+
year = NUM2LONG(argv[0]);
|
803
|
+
break;
|
804
|
+
case 0:
|
805
|
+
dt->flags = RHR_HAVE_JD | RHR_HAVE_NANOS | RHR_HAVE_HMS;
|
806
|
+
return rdt;
|
807
|
+
default:
|
808
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 7", argc);
|
809
|
+
break;
|
810
|
+
}
|
811
|
+
|
812
|
+
if(!rhrdt__valid_ordinal(dt, year, day)) {
|
813
|
+
RHR_CHECK_JD(dt)
|
814
|
+
rb_raise(rb_eArgError, "invalid date (year: %li, yday: %li)", year, day);
|
815
|
+
}
|
816
|
+
if (!rhrdt__valid_time(dt, hour, minute, second, offset)) {
|
817
|
+
rb_raise(rb_eArgError, "invalid time (hour: %li, minute: %li, second: %li, offset: %f)", hour, minute, second, offset);
|
818
|
+
}
|
819
|
+
return rdt;
|
820
|
+
}
|
821
|
+
|
822
|
+
/* call-seq:
|
823
|
+
* parse() -> DateTime <br />
|
824
|
+
* parse(string, comp=true, sg=nil) -> DateTime
|
825
|
+
*
|
826
|
+
* If no arguments are given, returns a +DateTime+ for julian day 0.
|
827
|
+
* Otherwise returns a +DateTime+ for the date represented by the given
|
828
|
+
* +string+. Raises an +ArgumentError+ if the string was not in
|
829
|
+
* a recognized format, or if the recognized format represents
|
830
|
+
* an invalid date or time.
|
831
|
+
* If +comp+ is true, expands 2-digit years to 4-digits years.
|
832
|
+
* Ignores the 3rd argument.
|
833
|
+
*/
|
834
|
+
static VALUE rhrdt_s_parse(int argc, VALUE *argv, VALUE klass) {
|
835
|
+
rhrdt_t *dt;
|
836
|
+
VALUE rdt = Data_Make_Struct(klass, rhrdt_t, NULL, free, dt);
|
837
|
+
|
838
|
+
switch(argc) {
|
839
|
+
case 0:
|
840
|
+
dt->flags = RHR_HAVE_JD | RHR_HAVE_NANOS | RHR_HAVE_HMS;
|
841
|
+
return rdt;
|
842
|
+
case 1:
|
843
|
+
rhrdt__fill_from_hash(dt, rb_funcall(klass, rhrd_id__parse, 1, argv[0]));
|
844
|
+
break;
|
845
|
+
case 2:
|
846
|
+
case 3:
|
847
|
+
rhrdt__fill_from_hash(dt, rb_funcall(klass, rhrd_id__parse, 2, argv[0], argv[1]));
|
848
|
+
break;
|
849
|
+
default:
|
850
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%i for 3)", argc);
|
851
|
+
break;
|
852
|
+
}
|
853
|
+
|
854
|
+
return rdt;
|
855
|
+
}
|
856
|
+
|
857
|
+
/* call-seq:
|
858
|
+
* strptime() -> DateTime <br />
|
859
|
+
* strptime(string, format="%FT%T%z", sg=nil) -> DateTime
|
860
|
+
*
|
861
|
+
* If no arguments are given, returns a +DateTime+ for julian day 0.
|
862
|
+
* Other returns a +DateTime+ for the date and time represented by the given
|
863
|
+
* +string+, parsed using the given +format+.
|
864
|
+
* Raises an +ArgumentError+ if the string did not match the format
|
865
|
+
* given, or if it did match and it represented an invalid date or time.
|
866
|
+
* Ignores the 3rd argument.
|
867
|
+
*/
|
868
|
+
static VALUE rhrdt_s_strptime(int argc, VALUE *argv, VALUE klass) {
|
869
|
+
rhrdt_t *dt;
|
870
|
+
VALUE rdt = Data_Make_Struct(klass, rhrdt_t, NULL, free, dt);
|
871
|
+
|
872
|
+
switch(argc) {
|
873
|
+
case 0:
|
874
|
+
dt->flags = RHR_HAVE_JD | RHR_HAVE_NANOS | RHR_HAVE_HMS;
|
875
|
+
return rdt;
|
876
|
+
case 3:
|
877
|
+
argc = 2;
|
878
|
+
case 1:
|
879
|
+
case 2:
|
880
|
+
break;
|
881
|
+
default:
|
882
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%i for 3)", argc);
|
883
|
+
break;
|
884
|
+
}
|
885
|
+
|
886
|
+
rhrdt__fill_from_hash(dt, rhrdt_s__strptime(argc, argv, klass));
|
887
|
+
return rdt;
|
888
|
+
}
|
889
|
+
|
890
|
+
/* Instance methods */
|
891
|
+
|
892
|
+
/* call-seq:
|
893
|
+
* _dump(limit) -> String
|
894
|
+
*
|
895
|
+
* Returns a marshalled representation of the receiver as a +String+.
|
896
|
+
* Generally not called directly, usually called by <tt>Marshal.dump</tt>.
|
897
|
+
*/
|
898
|
+
static VALUE rhrdt__dump(VALUE self, VALUE limit) {
|
899
|
+
rhrdt_t *d;
|
900
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
901
|
+
RHRDT_FILL_JD(d)
|
902
|
+
RHRDT_FILL_NANOS(d)
|
903
|
+
return rb_marshal_dump(rb_ary_new3(3, LONG2NUM(d->jd), LL2NUM(d->nanos), LONG2NUM(d->offset)), LONG2NUM(NUM2LONG(limit) - 1));
|
904
|
+
}
|
905
|
+
|
906
|
+
/* call-seq:
|
907
|
+
* ajd() -> Float
|
908
|
+
*
|
909
|
+
* Returns the date and time represented by the receiver as a
|
910
|
+
* astronomical julian day +Float+.
|
911
|
+
*/
|
912
|
+
static VALUE rhrdt_ajd(VALUE self) {
|
913
|
+
rhrdt_t *d;
|
914
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
915
|
+
RHRDT_FILL_JD(d)
|
916
|
+
RHRDT_FILL_NANOS(d)
|
917
|
+
return rb_float_new(d->jd + d->nanos/RHR_NANOS_PER_DAYD - d->offset/1440.0 - 0.5);
|
918
|
+
}
|
919
|
+
|
920
|
+
/* call-seq:
|
921
|
+
* amjd() -> Float
|
922
|
+
*
|
923
|
+
* Returns the date and time represented by the receiver as a
|
924
|
+
* astronomical modified julian day +Float+.
|
925
|
+
*/
|
926
|
+
static VALUE rhrdt_amjd(VALUE self) {
|
927
|
+
rhrdt_t *d;
|
928
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
929
|
+
RHRDT_FILL_JD(d)
|
930
|
+
RHRDT_FILL_NANOS(d)
|
931
|
+
return rb_float_new(d->jd + d->nanos/RHR_NANOS_PER_DAYD - d->offset/1440.0 - RHR_JD_MJD);
|
932
|
+
}
|
933
|
+
|
934
|
+
/* call-seq:
|
935
|
+
* asctime() -> String
|
936
|
+
*
|
937
|
+
* Returns a string representation of the receiver. Example:
|
938
|
+
*
|
939
|
+
* DateTime.civil(2009, 1, 2, 3, 4, 5).asctime
|
940
|
+
* # => "Fri Jan 2 03:04:05 2009"
|
941
|
+
*/
|
942
|
+
static VALUE rhrdt_asctime(VALUE self) {
|
943
|
+
VALUE s;
|
944
|
+
rhrdt_t *d;
|
945
|
+
int len;
|
946
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
947
|
+
RHRDT_FILL_CIVIL(d)
|
948
|
+
RHRDT_FILL_JD(d)
|
949
|
+
RHRDT_FILL_HMS(d)
|
950
|
+
|
951
|
+
s = rb_str_buf_new(128);
|
952
|
+
len = snprintf(RSTRING_PTR(s), 128, "%s %s %2hhi %02hhi:%02hhi:%02hhi %04li",
|
953
|
+
rhrd__abbr_day_names[rhrd__jd_to_wday(d->jd)],
|
954
|
+
rhrd__abbr_month_names[d->month],
|
955
|
+
d->day, d->hour, d->minute, d->second,
|
956
|
+
d->year);
|
957
|
+
if (len == -1 || len > 127) {
|
958
|
+
rb_raise(rb_eNoMemError, "in DateTime#asctime (in snprintf)");
|
959
|
+
}
|
960
|
+
|
961
|
+
RHR_RETURN_RESIZED_STR(s, len)
|
962
|
+
}
|
963
|
+
|
964
|
+
/* call-seq:
|
965
|
+
* cwday() -> Integer
|
966
|
+
*
|
967
|
+
* Returns the commercial week day as an +Integer+. Example:
|
968
|
+
*
|
969
|
+
* DateTime.civil(2009, 1, 2).cwday
|
970
|
+
* # => 5
|
971
|
+
* DateTime.civil(2010, 1, 2).cwday
|
972
|
+
* # => 6
|
973
|
+
*/
|
974
|
+
static VALUE rhrdt_cwday(VALUE self) {
|
975
|
+
rhrdt_t *d;
|
976
|
+
rhrd_t n;
|
977
|
+
RHR_CACHED_IV(self, rhrd_id_cwday)
|
978
|
+
memset(&n, 0, sizeof(rhrd_t));
|
979
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
980
|
+
RHRDT_FILL_JD(d)
|
981
|
+
n.jd = d->jd;
|
982
|
+
rhrd__fill_commercial(&n);
|
983
|
+
rhrd__set_cw_ivs(self, &n);
|
984
|
+
return LONG2NUM(n.day);
|
985
|
+
}
|
986
|
+
|
987
|
+
/* call-seq:
|
988
|
+
* cweek() -> Integer
|
989
|
+
*
|
990
|
+
* Returns the commercial week as an +Integer+. Example:
|
991
|
+
*
|
992
|
+
* DateTime.civil(2009, 1, 2).cweek
|
993
|
+
* # => 1
|
994
|
+
* DateTime.civil(2010, 1, 2).cweek
|
995
|
+
* # => 53
|
996
|
+
*/
|
997
|
+
static VALUE rhrdt_cweek(VALUE self) {
|
998
|
+
rhrdt_t *d;
|
999
|
+
rhrd_t n;
|
1000
|
+
RHR_CACHED_IV(self, rhrd_id_cweek)
|
1001
|
+
memset(&n, 0, sizeof(rhrd_t));
|
1002
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1003
|
+
RHRDT_FILL_JD(d)
|
1004
|
+
n.jd = d->jd;
|
1005
|
+
rhrd__fill_commercial(&n);
|
1006
|
+
rhrd__set_cw_ivs(self, &n);
|
1007
|
+
return LONG2NUM(n.month);
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
/* call-seq:
|
1011
|
+
* cwyear() -> Integer
|
1012
|
+
*
|
1013
|
+
* Returns the commercial week year as an +Integer+. Example:
|
1014
|
+
*
|
1015
|
+
* DateTime.civil(2009, 1, 2).cwyear
|
1016
|
+
* # => 2009
|
1017
|
+
* DateTime.civil(2010, 1, 2).cwyear
|
1018
|
+
* # => 2009
|
1019
|
+
*/
|
1020
|
+
static VALUE rhrdt_cwyear(VALUE self) {
|
1021
|
+
rhrdt_t *d;
|
1022
|
+
rhrd_t n;
|
1023
|
+
RHR_CACHED_IV(self, rhrd_id_cwyear)
|
1024
|
+
memset(&n, 0, sizeof(rhrd_t));
|
1025
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1026
|
+
RHRDT_FILL_JD(d)
|
1027
|
+
n.jd = d->jd;
|
1028
|
+
rhrd__fill_commercial(&n);
|
1029
|
+
rhrd__set_cw_ivs(self, &n);
|
1030
|
+
return LONG2NUM(n.year);
|
1031
|
+
}
|
1032
|
+
|
1033
|
+
/* call-seq:
|
1034
|
+
* day() -> Integer
|
1035
|
+
*
|
1036
|
+
* Returns the day of the month as an +Integer+. Example:
|
1037
|
+
*
|
1038
|
+
* DateTime.civil(2009, 1, 2).day
|
1039
|
+
* # => 2
|
1040
|
+
*/
|
1041
|
+
static VALUE rhrdt_day(VALUE self) {
|
1042
|
+
rhrdt_t *dt;
|
1043
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1044
|
+
RHRDT_FILL_CIVIL(dt)
|
1045
|
+
return LONG2NUM(dt->day);
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
/* call-seq:
|
1049
|
+
* day_fraction() -> Float
|
1050
|
+
*
|
1051
|
+
* Returns the fraction of the day as a +Float+. Example:
|
1052
|
+
*
|
1053
|
+
* DateTime.civil(2009, 1, 2).day_fraction
|
1054
|
+
* # => 0.0
|
1055
|
+
* DateTime.civil(2009, 1, 2, 12).day_fraction
|
1056
|
+
* # => 0.5
|
1057
|
+
* DateTime.civil(2009, 1, 2, 6).day_fraction
|
1058
|
+
* # => 0.25
|
1059
|
+
*/
|
1060
|
+
static VALUE rhrdt_day_fraction(VALUE self) {
|
1061
|
+
rhrdt_t *dt;
|
1062
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1063
|
+
RHRDT_FILL_NANOS(dt)
|
1064
|
+
return rb_float_new(dt->nanos/RHR_NANOS_PER_DAYD);
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
/* call-seq:
|
1068
|
+
* downto(target){|datetime|} -> DateTime
|
1069
|
+
*
|
1070
|
+
* Equivalent to calling +step+ with the +target+ as the first argument
|
1071
|
+
* and <tt>-1</tt> as the second argument. Returns self.
|
1072
|
+
*
|
1073
|
+
* DateTime.civil(2009, 1, 2).downto(DateTime.civil(2009, 1, 1)) do |datetime|
|
1074
|
+
* puts datetime
|
1075
|
+
* end
|
1076
|
+
* # Output:
|
1077
|
+
* # 2009-01-02T00:00:00+00:00
|
1078
|
+
* # 2009-01-01T00:00:00+00:00
|
1079
|
+
*/
|
1080
|
+
static VALUE rhrdt_downto(VALUE self, VALUE other) {
|
1081
|
+
VALUE argv[2];
|
1082
|
+
argv[0] = other;
|
1083
|
+
argv[1] = INT2FIX(-1);
|
1084
|
+
return rhrdt_step(2, argv, self);
|
1085
|
+
}
|
1086
|
+
|
1087
|
+
/* call-seq:
|
1088
|
+
* eql?(datetime) -> true or false
|
1089
|
+
*
|
1090
|
+
* Returns true only if the +datetime+ given is the same date and time as the receiver.
|
1091
|
+
* If +date+ is an instance of +Date+, returns +true+ only if +date+ is
|
1092
|
+
* for the same date as the receiver and the receiver has no fractional component.
|
1093
|
+
* Otherwise, returns +false+. Example:
|
1094
|
+
*
|
1095
|
+
* DateTime.civil(2009, 1, 2, 12).eql?(DateTime.civil(2009, 1, 2, 12))
|
1096
|
+
* # => true
|
1097
|
+
* DateTime.civil(2009, 1, 2, 12).eql?(DateTime.civil(2009, 1, 2, 11))
|
1098
|
+
* # => false
|
1099
|
+
* DateTime.civil(2009, 1, 2).eql?(Date.civil(2009, 1, 2))
|
1100
|
+
* # => true
|
1101
|
+
* DateTime.civil(2009, 1, 2, 1).eql?(Date.civil(2009, 1, 2))
|
1102
|
+
* # => false
|
1103
|
+
*/
|
1104
|
+
static VALUE rhrdt_eql_q(VALUE self, VALUE other) {
|
1105
|
+
rhrdt_t *dt, *odt;
|
1106
|
+
rhrd_t *o;
|
1107
|
+
long diff;
|
1108
|
+
|
1109
|
+
if (RTEST(rb_obj_is_kind_of(other, rhrdt_class))) {
|
1110
|
+
self = rhrdt__new_offset(self, 0);
|
1111
|
+
other = rhrdt__new_offset(other, 0);
|
1112
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1113
|
+
Data_Get_Struct(other, rhrdt_t, odt);
|
1114
|
+
return rhrdt__spaceship(dt, odt) == 0 ? Qtrue : Qfalse;
|
1115
|
+
} else if (RTEST(rb_obj_is_kind_of(other, rhrd_class))) {
|
1116
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1117
|
+
Data_Get_Struct(other, rhrd_t, o);
|
1118
|
+
RHRDT_FILL_JD(dt)
|
1119
|
+
RHR_FILL_JD(o)
|
1120
|
+
RHR_SPACE_SHIP(diff, dt->jd, o->jd)
|
1121
|
+
if (diff == 0) {
|
1122
|
+
RHRDT_FILL_NANOS(dt)
|
1123
|
+
RHR_SPACE_SHIP(diff, dt->nanos, 0)
|
1124
|
+
}
|
1125
|
+
return diff == 0 ? Qtrue : Qfalse;
|
1126
|
+
}
|
1127
|
+
return Qfalse;
|
1128
|
+
}
|
1129
|
+
|
1130
|
+
/* call-seq:
|
1131
|
+
* hash() -> Integer
|
1132
|
+
*
|
1133
|
+
* Return an +Integer+ hash value for the receiver, such that an
|
1134
|
+
* equal date and time will have the same hash value.
|
1135
|
+
*/
|
1136
|
+
static VALUE rhrdt_hash(VALUE self) {
|
1137
|
+
rhrdt_t *d;
|
1138
|
+
RHR_CACHED_IV(self, rhrd_id_hash)
|
1139
|
+
Data_Get_Struct(rhrdt__new_offset(self, 0), rhrdt_t, d);
|
1140
|
+
return rb_ivar_set(self, rhrd_id_hash, rb_funcall(rb_ary_new3(2, LONG2NUM(d->jd), LL2NUM(d->nanos)), rhrd_id_hash, 0));
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
/* call-seq:
|
1144
|
+
* hour() -> Integer
|
1145
|
+
*
|
1146
|
+
* Returns the hour of the day as an +Integer+. Example:
|
1147
|
+
*
|
1148
|
+
* DateTime.civil(2009, 1, 2, 12, 13, 14).hour
|
1149
|
+
* # => 12
|
1150
|
+
*/
|
1151
|
+
static VALUE rhrdt_hour(VALUE self) {
|
1152
|
+
rhrdt_t *dt;
|
1153
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1154
|
+
RHRDT_FILL_HMS(dt)
|
1155
|
+
return LONG2NUM(dt->hour);
|
1156
|
+
}
|
1157
|
+
|
1158
|
+
/* call-seq:
|
1159
|
+
* inspect() -> String
|
1160
|
+
*
|
1161
|
+
* Return a developer-friendly string containing the civil
|
1162
|
+
* date and time for the receiver. Example:
|
1163
|
+
*
|
1164
|
+
* DateTime.civil(2009, 1, 2, 3, 4, 5, 0.5).inspect
|
1165
|
+
* # => "#<DateTime 2009-01-02T03:04:05+12:00>"
|
1166
|
+
*/
|
1167
|
+
static VALUE rhrdt_inspect(VALUE self) {
|
1168
|
+
VALUE s;
|
1169
|
+
rhrdt_t *dt;
|
1170
|
+
int len;
|
1171
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1172
|
+
RHRDT_FILL_CIVIL(dt)
|
1173
|
+
RHRDT_FILL_HMS(dt)
|
1174
|
+
|
1175
|
+
s = rb_str_buf_new(128);
|
1176
|
+
len = snprintf(RSTRING_PTR(s), 128, "#<DateTime %04li-%02hhi-%02hhiT%02hhi:%02hhi:%02hhi%+03i:%02i>",
|
1177
|
+
dt->year, dt->month, dt->day, dt->hour, dt->minute, dt->second, dt->offset/60, abs(dt->offset % 60));
|
1178
|
+
if (len == -1 || len > 127) {
|
1179
|
+
rb_raise(rb_eNoMemError, "in DateTime#inspect (in snprintf)");
|
1180
|
+
}
|
1181
|
+
|
1182
|
+
RHR_RETURN_RESIZED_STR(s, len)
|
1183
|
+
}
|
1184
|
+
|
1185
|
+
/* call-seq:
|
1186
|
+
* jd() -> Integer
|
1187
|
+
*
|
1188
|
+
* Return the julian day number for the receiver as an +Integer+.
|
1189
|
+
*
|
1190
|
+
* DateTime.civil(2009, 1, 2).jd
|
1191
|
+
* # => 2454834
|
1192
|
+
*/
|
1193
|
+
static VALUE rhrdt_jd(VALUE self) {
|
1194
|
+
rhrdt_t *d;
|
1195
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1196
|
+
RHRDT_FILL_JD(d)
|
1197
|
+
return LONG2NUM(d->jd);
|
1198
|
+
}
|
1199
|
+
|
1200
|
+
/* call-seq:
|
1201
|
+
* ld() -> Integer
|
1202
|
+
*
|
1203
|
+
* Return the number of days since the Lilian Date (the day of calendar reform
|
1204
|
+
* in Italy).
|
1205
|
+
*
|
1206
|
+
* DateTime.civil(2009, 1, 2).ld
|
1207
|
+
* # => 155674
|
1208
|
+
*/
|
1209
|
+
static VALUE rhrdt_ld(VALUE self) {
|
1210
|
+
rhrdt_t *d;
|
1211
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1212
|
+
RHRDT_FILL_JD(d)
|
1213
|
+
return LONG2NUM(d->jd - RHR_JD_LD);
|
1214
|
+
}
|
1215
|
+
|
1216
|
+
/* call-seq:
|
1217
|
+
* leap?() -> true or false
|
1218
|
+
*
|
1219
|
+
* Return +true+ if the current year for this date is a leap year
|
1220
|
+
* in the Gregorian calendar, +false+ otherwise.
|
1221
|
+
*
|
1222
|
+
* DateTime.civil(2009, 1, 2).leap?
|
1223
|
+
* # => false
|
1224
|
+
* DateTime.civil(2008, 1, 2).leap?
|
1225
|
+
* # => true
|
1226
|
+
*/
|
1227
|
+
static VALUE rhrdt_leap_q(VALUE self) {
|
1228
|
+
rhrdt_t *d;
|
1229
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1230
|
+
RHRDT_FILL_CIVIL(d)
|
1231
|
+
return rhrd__leap_year(d->year) ? Qtrue : Qfalse;
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
/* call-seq:
|
1235
|
+
* min() -> Integer
|
1236
|
+
*
|
1237
|
+
* Returns the minute of the hour as an +Integer+. Example:
|
1238
|
+
*
|
1239
|
+
* DateTime.civil(2009, 1, 2, 12, 13, 14).min
|
1240
|
+
* # => 13
|
1241
|
+
*/
|
1242
|
+
static VALUE rhrdt_min(VALUE self) {
|
1243
|
+
rhrdt_t *dt;
|
1244
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1245
|
+
RHRDT_FILL_HMS(dt)
|
1246
|
+
return LONG2NUM(dt->minute);
|
1247
|
+
}
|
1248
|
+
|
1249
|
+
/* call-seq:
|
1250
|
+
* mjd() -> Integer
|
1251
|
+
*
|
1252
|
+
* Return the number of days since 1858-11-17.
|
1253
|
+
*
|
1254
|
+
* DateTime.civil(2009, 1, 2).mjd
|
1255
|
+
* # => 54833
|
1256
|
+
*/
|
1257
|
+
static VALUE rhrdt_mjd(VALUE self) {
|
1258
|
+
rhrdt_t *d;
|
1259
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1260
|
+
RHRDT_FILL_JD(d)
|
1261
|
+
return LONG2NUM(d->jd - RHR_JD_MJD);
|
1262
|
+
}
|
1263
|
+
|
1264
|
+
/* call-seq:
|
1265
|
+
* month() -> Integer
|
1266
|
+
*
|
1267
|
+
* Returns the number of the month as an +Integer+. Example:
|
1268
|
+
*
|
1269
|
+
* DateTime.civil(2009, 1, 2).month
|
1270
|
+
* # => 1
|
1271
|
+
*/
|
1272
|
+
static VALUE rhrdt_month(VALUE self) {
|
1273
|
+
rhrdt_t *dt;
|
1274
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1275
|
+
RHRDT_FILL_CIVIL(dt)
|
1276
|
+
return LONG2NUM(dt->month);
|
1277
|
+
}
|
1278
|
+
|
1279
|
+
/* call-seq:
|
1280
|
+
* new_offset() -> DateTime
|
1281
|
+
*
|
1282
|
+
* Returns a +DateTime+ with the same absolute time as the current
|
1283
|
+
* time, but a potentially different local time. The returned value will
|
1284
|
+
* be equal to the receiver.
|
1285
|
+
* Raises +ArgumentError+ if an invalid offset is specified.
|
1286
|
+
* Example:
|
1287
|
+
*
|
1288
|
+
* DateTime.civil(2009, 1, 2).new_offset(0.5)
|
1289
|
+
* # => #<DateTime 2009-01-02T12:00:00+12:00>
|
1290
|
+
* DateTime.civil(2009, 1, 2).new_offset(0.5)
|
1291
|
+
* # => #<DateTime 2009-01-01T12:00:00-12:00>
|
1292
|
+
*/
|
1293
|
+
static VALUE rhrdt_new_offset(int argc, VALUE *argv, VALUE self) {
|
1294
|
+
double offset;
|
1295
|
+
|
1296
|
+
switch(argc) {
|
1297
|
+
case 0:
|
1298
|
+
offset = 0;
|
1299
|
+
break;
|
1300
|
+
case 1:
|
1301
|
+
if (RTEST(rb_obj_is_kind_of(argv[0], rb_cString))) {
|
1302
|
+
offset = NUM2LONG(rhrd_s_zone_to_diff(self, argv[0]))/RHR_SECONDS_PER_DAYD;
|
1303
|
+
} else {
|
1304
|
+
offset = NUM2DBL(argv[0]);
|
1305
|
+
}
|
1306
|
+
break;
|
1307
|
+
default:
|
1308
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
1309
|
+
break;
|
1310
|
+
}
|
1311
|
+
return rhrdt__new_offset(self, offset);
|
1312
|
+
}
|
1313
|
+
|
1314
|
+
/* call-seq:
|
1315
|
+
* next() -> DateTime
|
1316
|
+
*
|
1317
|
+
* Returns the +DateTime+ after the receiver's date. If the receiver
|
1318
|
+
* has a fractional day component, the result will have the same
|
1319
|
+
* fractional day component.
|
1320
|
+
*
|
1321
|
+
* DateTime.civil(2009, 1, 2, 12).next
|
1322
|
+
* # => #<DateTime 2009-01-03T12:00:00+00:00>
|
1323
|
+
*/
|
1324
|
+
static VALUE rhrdt_next(VALUE self) {
|
1325
|
+
return rhrdt__add_days(self, 1);
|
1326
|
+
}
|
1327
|
+
|
1328
|
+
/* call-seq:
|
1329
|
+
* offset() -> Float
|
1330
|
+
*
|
1331
|
+
* Returns a +Float+ representing the offset from UTC as a fraction
|
1332
|
+
* of the day, where 0.5 would be 12 hours ahead of UTC ("+12:00"),
|
1333
|
+
* and -0.5 would be 12 hours behind UTC ("-12:00").
|
1334
|
+
*
|
1335
|
+
* DateTime.civil(2009, 1, 2, 12, 13, 14, -0.5).offset
|
1336
|
+
* # => -0.5
|
1337
|
+
*/
|
1338
|
+
static VALUE rhrdt_offset(VALUE self) {
|
1339
|
+
rhrdt_t *dt;
|
1340
|
+
RHR_CACHED_IV(self, rhrd_id_offset)
|
1341
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1342
|
+
return rb_ivar_set(self, rhrd_id_offset, rb_float_new(dt->offset/1440.0));
|
1343
|
+
}
|
1344
|
+
|
1345
|
+
/* call-seq:
|
1346
|
+
* sec() -> Integer
|
1347
|
+
*
|
1348
|
+
* Returns the second of the minute as an +Integer+. Example:
|
1349
|
+
*
|
1350
|
+
* DateTime.civil(2009, 1, 2, 12, 13, 14).sec
|
1351
|
+
* # => 14
|
1352
|
+
*/
|
1353
|
+
static VALUE rhrdt_sec(VALUE self) {
|
1354
|
+
rhrdt_t *dt;
|
1355
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1356
|
+
RHRDT_FILL_HMS(dt)
|
1357
|
+
return LONG2NUM(dt->second);
|
1358
|
+
}
|
1359
|
+
|
1360
|
+
/* call-seq:
|
1361
|
+
* sec_fraction() -> Float
|
1362
|
+
*
|
1363
|
+
* Returns a +Float+ representing the fraction of the second as a
|
1364
|
+
* fraction of the day, which will always be in the range [0.0, 1/86400.0).
|
1365
|
+
*
|
1366
|
+
* (DateTime.civil(2009, 1, 2, 12, 13, 14) + (1.5/86400)).sec_fraction
|
1367
|
+
* # => 0.000005787037
|
1368
|
+
*/
|
1369
|
+
static VALUE rhrdt_sec_fraction(VALUE self) {
|
1370
|
+
rhrdt_t *dt;
|
1371
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1372
|
+
RHRDT_FILL_NANOS(dt)
|
1373
|
+
return rb_float_new((dt->nanos % RHR_NANOS_PER_SECOND)/RHR_NANOS_PER_DAYD);
|
1374
|
+
}
|
1375
|
+
|
1376
|
+
/* call-seq:
|
1377
|
+
* step(target, step=1){|datetime|} -> DateTime
|
1378
|
+
*
|
1379
|
+
* Yields +DateTime+ objects between the receiver and the +target+ date
|
1380
|
+
* (inclusive), with +step+ days between each yielded date.
|
1381
|
+
* +step+ may be a an +Integer+, in which case whole days are added,
|
1382
|
+
* or it can be a +Float+, in which case fractional days are added.
|
1383
|
+
* +step+ can be negative, in which case the dates are yielded in
|
1384
|
+
* reverse chronological order. Returns self in all cases.
|
1385
|
+
*
|
1386
|
+
* If +target+ is equal to the receiver, yields self once regardless of
|
1387
|
+
* +step+. It +target+ is less than receiver and +step+ is nonnegative, or
|
1388
|
+
* +target+ is greater than receiver and +step+ is nonpositive, does not
|
1389
|
+
* yield.
|
1390
|
+
*
|
1391
|
+
* DateTime.civil(2009, 1, 2).step(DateTime.civil(2009, 1, 6), 2) do |datetime|
|
1392
|
+
* puts datetime
|
1393
|
+
* end
|
1394
|
+
* # Output:
|
1395
|
+
* # 2009-01-02T00:00:00+00:00
|
1396
|
+
* # 2009-01-04T00:00:00+00:00
|
1397
|
+
* # 2009-01-06T00:00:00+00:00
|
1398
|
+
* #
|
1399
|
+
*/
|
1400
|
+
static VALUE rhrdt_step(int argc, VALUE *argv, VALUE self) {
|
1401
|
+
rhrdt_t *d, *ndt, *d0;
|
1402
|
+
rhrd_t *nd;
|
1403
|
+
double step, limit;
|
1404
|
+
long long step_nanos, limit_nanos, current_nanos;
|
1405
|
+
long step_jd, limit_jd, current_jd;
|
1406
|
+
VALUE rlimit, new;
|
1407
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1408
|
+
Data_Get_Struct(rhrdt__new_offset(self, 0), rhrdt_t, d0);
|
1409
|
+
|
1410
|
+
rb_need_block();
|
1411
|
+
switch(argc) {
|
1412
|
+
case 1:
|
1413
|
+
step_nanos = 0;
|
1414
|
+
step_jd = 1;
|
1415
|
+
break;
|
1416
|
+
case 2:
|
1417
|
+
step = NUM2DBL(argv[1]);
|
1418
|
+
step_jd = floor(step);
|
1419
|
+
step_nanos = llround((step - step_jd)*RHR_NANOS_PER_DAY);
|
1420
|
+
break;
|
1421
|
+
default:
|
1422
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 2", argc);
|
1423
|
+
break;
|
1424
|
+
}
|
1425
|
+
|
1426
|
+
rlimit = argv[0];
|
1427
|
+
if (RTEST(rb_obj_is_kind_of(rlimit, rb_cNumeric))) {
|
1428
|
+
limit = NUM2DBL(rlimit);
|
1429
|
+
limit_jd = floor(limit);
|
1430
|
+
limit_nanos = llround((limit - limit_jd)*RHR_NANOS_PER_DAY);
|
1431
|
+
} else if (RTEST((rb_obj_is_kind_of(rlimit, rhrdt_class)))) {
|
1432
|
+
rlimit = rhrdt__new_offset(rlimit, 0);
|
1433
|
+
Data_Get_Struct(rlimit, rhrdt_t, ndt);
|
1434
|
+
RHRDT_FILL_JD(ndt)
|
1435
|
+
RHRDT_FILL_NANOS(ndt)
|
1436
|
+
limit_jd = ndt->jd;
|
1437
|
+
limit_nanos = ndt->nanos;
|
1438
|
+
} else if (RTEST((rb_obj_is_kind_of(rlimit, rhrd_class)))) {
|
1439
|
+
Data_Get_Struct(rlimit, rhrd_t, nd);
|
1440
|
+
RHR_FILL_JD(nd)
|
1441
|
+
limit_jd = nd->jd;
|
1442
|
+
limit_nanos = d->offset*RHR_NANOS_PER_MINUTE;
|
1443
|
+
if (limit_nanos < 0) {
|
1444
|
+
limit_jd--;
|
1445
|
+
limit_nanos += RHR_NANOS_PER_DAY;
|
1446
|
+
}
|
1447
|
+
} else {
|
1448
|
+
rb_raise(rb_eTypeError, "expected numeric or date");
|
1449
|
+
}
|
1450
|
+
|
1451
|
+
current_jd = d0->jd;
|
1452
|
+
current_nanos = d0->nanos;
|
1453
|
+
new = rhrdt__from_jd_nanos(current_jd, current_nanos, d->offset);
|
1454
|
+
if (limit_jd > current_jd || (limit_jd == current_jd && limit_nanos > current_nanos)) {
|
1455
|
+
if (step_jd > 0 || (step_jd == 0 && step_nanos > 0)) {
|
1456
|
+
while (limit_jd > current_jd || (limit_jd == current_jd && limit_nanos >= current_nanos)) {
|
1457
|
+
rb_yield(new);
|
1458
|
+
new = rhrdt__from_jd_nanos(current_jd + step_jd, current_nanos + step_nanos, d->offset);
|
1459
|
+
Data_Get_Struct(new, rhrdt_t, ndt);
|
1460
|
+
current_jd = ndt->jd;
|
1461
|
+
current_nanos = ndt->nanos;
|
1462
|
+
}
|
1463
|
+
}
|
1464
|
+
} else if (limit_jd < current_jd || (limit_jd == current_jd && limit_nanos < current_nanos)) {
|
1465
|
+
if (step_jd < 0 || (step_jd == 0 && step_nanos < 0)) {
|
1466
|
+
while (limit_jd < current_jd || (limit_jd == current_jd && limit_nanos <= current_nanos)) {
|
1467
|
+
rb_yield(new);
|
1468
|
+
new = rhrdt__from_jd_nanos(current_jd + step_jd, current_nanos + step_nanos, d->offset);
|
1469
|
+
Data_Get_Struct(new, rhrdt_t, ndt);
|
1470
|
+
current_jd = ndt->jd;
|
1471
|
+
current_nanos = ndt->nanos;
|
1472
|
+
}
|
1473
|
+
}
|
1474
|
+
} else {
|
1475
|
+
rb_yield(self);
|
1476
|
+
}
|
1477
|
+
|
1478
|
+
return self;
|
1479
|
+
}
|
1480
|
+
|
1481
|
+
/* call-seq:
|
1482
|
+
* strftime() -> String <br />
|
1483
|
+
* strftime(format) -> String
|
1484
|
+
*
|
1485
|
+
* If no argument is provided, returns a string in ISO8601 format, just like
|
1486
|
+
* +to_s+. If an argument is provided, uses it as a format string and returns
|
1487
|
+
* a +String+ based on the format. See <tt>Date#strftime</tt> for the supported
|
1488
|
+
* formats.
|
1489
|
+
*/
|
1490
|
+
static VALUE rhrdt_strftime(int argc, VALUE *argv, VALUE self) {
|
1491
|
+
rhrdt_t* dt;
|
1492
|
+
VALUE r;
|
1493
|
+
|
1494
|
+
switch(argc) {
|
1495
|
+
case 0:
|
1496
|
+
return rhrdt_to_s(self);
|
1497
|
+
case 1:
|
1498
|
+
r = rb_str_to_str(argv[0]);
|
1499
|
+
break;
|
1500
|
+
default:
|
1501
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
1502
|
+
break;
|
1503
|
+
}
|
1504
|
+
|
1505
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1506
|
+
RHRDT_FILL_CIVIL(dt)
|
1507
|
+
RHRDT_FILL_JD(dt)
|
1508
|
+
RHRDT_FILL_HMS(dt)
|
1509
|
+
RHRDT_FILL_NANOS(dt)
|
1510
|
+
return rhrd__strftime(dt, RSTRING_PTR(r), RSTRING_LEN(r));
|
1511
|
+
}
|
1512
|
+
|
1513
|
+
/* call-seq:
|
1514
|
+
* to_s() -> String
|
1515
|
+
*
|
1516
|
+
* Returns the receiver as an ISO8601 formatted string.
|
1517
|
+
*
|
1518
|
+
* DateTime.civil(2009, 1, 2, 12, 13, 14, 0.5).to_s
|
1519
|
+
* # => "2009-01-02T12:13:14+12:00"
|
1520
|
+
*/
|
1521
|
+
static VALUE rhrdt_to_s(VALUE self) {
|
1522
|
+
VALUE s;
|
1523
|
+
rhrdt_t *dt;
|
1524
|
+
int len;
|
1525
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1526
|
+
RHRDT_FILL_CIVIL(dt)
|
1527
|
+
RHRDT_FILL_HMS(dt)
|
1528
|
+
|
1529
|
+
s = rb_str_buf_new(128);
|
1530
|
+
len = snprintf(RSTRING_PTR(s), 128, "%04li-%02hhi-%02hhiT%02hhi:%02hhi:%02hhi%+03i:%02i",
|
1531
|
+
dt->year, dt->month, dt->day, dt->hour, dt->minute, dt->second, dt->offset/60, abs(dt->offset % 60));
|
1532
|
+
if (len == -1 || len > 127) {
|
1533
|
+
rb_raise(rb_eNoMemError, "in DateTime#to_s (in snprintf)");
|
1534
|
+
}
|
1535
|
+
|
1536
|
+
RHR_RETURN_RESIZED_STR(s, len)
|
1537
|
+
}
|
1538
|
+
|
1539
|
+
/* call-seq:
|
1540
|
+
* upto(target){|datetime|} -> DateTime
|
1541
|
+
*
|
1542
|
+
* Equivalent to calling +step+ with the +target+ as the first argument. Returns self.
|
1543
|
+
*
|
1544
|
+
* DateTime.civil(2009, 1, 1).upto(DateTime.civil(2009, 1, 2)) do |datetime|
|
1545
|
+
* puts datetime
|
1546
|
+
* end
|
1547
|
+
* # Output:
|
1548
|
+
* # 2009-01-01T00:00:00+00:00
|
1549
|
+
* # 2009-01-02T00:00:00+00:00
|
1550
|
+
*/
|
1551
|
+
static VALUE rhrdt_upto(VALUE self, VALUE other) {
|
1552
|
+
VALUE argv[1];
|
1553
|
+
argv[0] = other;
|
1554
|
+
return rhrdt_step(1, argv, self);
|
1555
|
+
}
|
1556
|
+
|
1557
|
+
/* call-seq:
|
1558
|
+
* wday() -> Integer
|
1559
|
+
*
|
1560
|
+
* Returns the day of the week as an +Integer+, where Sunday
|
1561
|
+
* is 0 and Saturday is 6. Example:
|
1562
|
+
*
|
1563
|
+
* DateTime.civil(2009, 1, 2).wday
|
1564
|
+
* # => 5
|
1565
|
+
*/
|
1566
|
+
static VALUE rhrdt_wday(VALUE self) {
|
1567
|
+
rhrdt_t *d;
|
1568
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1569
|
+
RHRDT_FILL_JD(d)
|
1570
|
+
return LONG2NUM(rhrd__jd_to_wday(d->jd));
|
1571
|
+
}
|
1572
|
+
|
1573
|
+
/* call-seq:
|
1574
|
+
* yday() -> Integer
|
1575
|
+
*
|
1576
|
+
* Returns the day of the year as an +Integer+, where January
|
1577
|
+
* 1st is 1 and December 31 is 365 (or 366 if the year is a leap
|
1578
|
+
* year). Example:
|
1579
|
+
*
|
1580
|
+
* DateTime.civil(2009, 2, 2).yday
|
1581
|
+
* # => 33
|
1582
|
+
*/
|
1583
|
+
static VALUE rhrdt_yday(VALUE self) {
|
1584
|
+
rhrdt_t *d;
|
1585
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1586
|
+
RHRDT_FILL_CIVIL(d)
|
1587
|
+
return LONG2NUM(rhrd__ordinal_day(d->year, d->month, d->day));
|
1588
|
+
}
|
1589
|
+
|
1590
|
+
/* call-seq:
|
1591
|
+
* year() -> Integer
|
1592
|
+
*
|
1593
|
+
* Returns the year as an +Integer+. Example:
|
1594
|
+
*
|
1595
|
+
* DateTime.civil(2009, 1, 2).year
|
1596
|
+
* # => 2009
|
1597
|
+
*/
|
1598
|
+
static VALUE rhrdt_year(VALUE self) {
|
1599
|
+
rhrdt_t *dt;
|
1600
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1601
|
+
RHRDT_FILL_CIVIL(dt)
|
1602
|
+
return LONG2NUM(dt->year);
|
1603
|
+
}
|
1604
|
+
|
1605
|
+
/* call-seq:
|
1606
|
+
* zone() -> String
|
1607
|
+
*
|
1608
|
+
* Returns the time zone as a formatted string. This always uses
|
1609
|
+
* a numeric representation based on the offset, as +DateTime+ instances
|
1610
|
+
* do not keep information about named timezones.
|
1611
|
+
*
|
1612
|
+
* DateTime.civil(2009, 1, 2, 12, 13, 14, 0.5).zone
|
1613
|
+
* # => "+12:00"
|
1614
|
+
*/
|
1615
|
+
static VALUE rhrdt_zone(VALUE self) {
|
1616
|
+
VALUE s;
|
1617
|
+
rhrdt_t *dt;
|
1618
|
+
int len;
|
1619
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1620
|
+
|
1621
|
+
s = rb_str_buf_new(128);
|
1622
|
+
len = snprintf(RSTRING_PTR(s), 128, "%+03i:%02i", dt->offset/60, abs(dt->offset % 60));
|
1623
|
+
if (len == -1 || len > 127) {
|
1624
|
+
rb_raise(rb_eNoMemError, "in DateTime#zone (in snprintf)");
|
1625
|
+
}
|
1626
|
+
|
1627
|
+
RHR_RETURN_RESIZED_STR(s, len)
|
1628
|
+
}
|
1629
|
+
|
1630
|
+
/* Ruby instance operator methods */
|
1631
|
+
|
1632
|
+
/* call-seq:
|
1633
|
+
* >>(n) -> DateTime
|
1634
|
+
*
|
1635
|
+
* Returns a +DateTime+ that is +n+ months after the receiver. +n+
|
1636
|
+
* can be negative, in which case it returns a +DateTime+ before
|
1637
|
+
* the receiver.
|
1638
|
+
*
|
1639
|
+
* DateTime.civil(2009, 1, 2) >> 2
|
1640
|
+
* # => #<DateTime 2009-03-02T00:00:00+00:00>
|
1641
|
+
* DateTime.civil(2009, 1, 2) >> -2
|
1642
|
+
* # => #<DateTime 2008-11-02T00:00:00+00:00>
|
1643
|
+
*/
|
1644
|
+
static VALUE rhrdt_op_right_shift(VALUE self, VALUE other) {
|
1645
|
+
return rhrdt__add_months(self, NUM2LONG(other));
|
1646
|
+
}
|
1647
|
+
|
1648
|
+
/* call-seq:
|
1649
|
+
* <<(n) -> DateTime
|
1650
|
+
*
|
1651
|
+
* Returns a +DateTime+ that is +n+ months before the receiver. +n+
|
1652
|
+
* can be negative, in which case it returns a +DateTime+ after
|
1653
|
+
* the receiver.
|
1654
|
+
*
|
1655
|
+
* DateTime.civil(2009, 1, 2) << 2
|
1656
|
+
* # => #<DateTime 2008-11-02T00:00:00+00:00>
|
1657
|
+
* DateTime.civil(2009, 1, 2) << -2
|
1658
|
+
* # => #<DateTime 2009-03-02T00:00:00+00:00>
|
1659
|
+
*/
|
1660
|
+
static VALUE rhrdt_op_left_shift(VALUE self, VALUE other) {
|
1661
|
+
return rhrdt__add_months(self, -NUM2LONG(other));
|
1662
|
+
}
|
1663
|
+
|
1664
|
+
/* call-seq:
|
1665
|
+
* +(n) -> DateTime
|
1666
|
+
*
|
1667
|
+
* Returns a +DateTime+ that is +n+ days after the receiver. +n+
|
1668
|
+
* can be negative, in which case it returns a +DateTime+ before
|
1669
|
+
* the receiver. +n+ can be a +Float+ including a fractional part,
|
1670
|
+
* in which case it is added as a partial day.
|
1671
|
+
*
|
1672
|
+
* DateTime.civil(2009, 1, 2, 6, 0, 0) + 2
|
1673
|
+
* # => #<DateTime 2009-01-04T06:00:00+00:00>
|
1674
|
+
* DateTime.civil(2009, 1, 2, 6, 0, 0) + -2
|
1675
|
+
* # => #<DateTime 2008-12-31T06:00:00+00:00>
|
1676
|
+
* DateTime.civil(2009, 1, 2, 6, 0, 0) + 0.5
|
1677
|
+
* # => #<DateTime 2009-01-02T18:00:00+00:00>
|
1678
|
+
*/
|
1679
|
+
static VALUE rhrdt_op_plus(VALUE self, VALUE other) {
|
1680
|
+
return rhrdt__add_days(self, NUM2DBL(other));
|
1681
|
+
}
|
1682
|
+
|
1683
|
+
/* call-seq:
|
1684
|
+
* -(n) -> DateTime <br />
|
1685
|
+
* -(date) -> Float <br />
|
1686
|
+
* -(datetime) -> Float
|
1687
|
+
*
|
1688
|
+
* If a +Numeric+ argument is given, it is treated as an +Float+,
|
1689
|
+
* and the number of days it represents is substracted from the
|
1690
|
+
* receiver to return a new +DateTime+ object. +n+ can be negative, in
|
1691
|
+
* which case the +DateTime+ returned will be after the receiver.
|
1692
|
+
*
|
1693
|
+
* If a +Date+ argument is given, returns the number of days
|
1694
|
+
* between the current date and the argument as an +Float+. If
|
1695
|
+
* the receiver has no fractional component, will return a +Float+
|
1696
|
+
* with no fractional component. The +Date+ argument is assumed to
|
1697
|
+
* have the same time zone offset as the receiver.
|
1698
|
+
*
|
1699
|
+
* If a +DateTime+ argument is given, returns the number of days
|
1700
|
+
* between the receiver and the argument as a +Float+. This
|
1701
|
+
* handles differences in the time zone offsets between the
|
1702
|
+
* receiver and the argument.
|
1703
|
+
*
|
1704
|
+
* Other types of arguments raise a +TypeError+.
|
1705
|
+
*
|
1706
|
+
* DateTime.civil(2009, 1, 2) - 2
|
1707
|
+
* # => #<DateTime 2008-12-31T00:00:00+00:00>
|
1708
|
+
* DateTime.civil(2009, 1, 2) - 2.5
|
1709
|
+
* # => #<DateTime 2008-12-30T12:00:00+00:00>
|
1710
|
+
* DateTime.civil(2009, 1, 2) - Date.civil(2009, 1, 1)
|
1711
|
+
* # => 1.0
|
1712
|
+
* DateTime.civil(2009, 1, 2, 12, 0, 0) - Date.civil(2009, 1, 1)
|
1713
|
+
* # => 1.5
|
1714
|
+
* DateTime.civil(2009, 1, 2, 12, 0, 0, 0.5) - Date.civil(2009, 1, 1)
|
1715
|
+
* # => 1.5
|
1716
|
+
* DateTime.civil(2009, 1, 2) - DateTime.civil(2009, 1, 3, 12)
|
1717
|
+
* # => -1.5
|
1718
|
+
* DateTime.civil(2009, 1, 2, 0, 0, 0, 0.5) - DateTime.civil(2009, 1, 3, 12, 0, 0, -0.5)
|
1719
|
+
* # => -2.5
|
1720
|
+
*/
|
1721
|
+
static VALUE rhrdt_op_minus(VALUE self, VALUE other) {
|
1722
|
+
rhrdt_t *dt;
|
1723
|
+
rhrdt_t *newdt;
|
1724
|
+
rhrd_t *newd;
|
1725
|
+
|
1726
|
+
if (RTEST(rb_obj_is_kind_of(other, rb_cNumeric))) {
|
1727
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1728
|
+
return rhrdt__add_days(self, -NUM2DBL(other));
|
1729
|
+
}
|
1730
|
+
if (RTEST((rb_obj_is_kind_of(other, rhrdt_class)))) {
|
1731
|
+
self = rhrdt__new_offset(self, 0);
|
1732
|
+
other = rhrdt__new_offset(other, 0);
|
1733
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1734
|
+
Data_Get_Struct(other, rhrdt_t, newdt);
|
1735
|
+
RHRDT_FILL_JD(dt)
|
1736
|
+
RHRDT_FILL_NANOS(dt)
|
1737
|
+
RHRDT_FILL_JD(newdt)
|
1738
|
+
RHRDT_FILL_NANOS(newdt)
|
1739
|
+
if (dt->nanos == newdt->nanos) {
|
1740
|
+
return rb_float_new(dt->jd - newdt->jd);
|
1741
|
+
} else if (dt->jd == newdt->jd)
|
1742
|
+
return rb_float_new((dt->nanos - newdt->nanos)/RHR_NANOS_PER_DAYD);
|
1743
|
+
else {
|
1744
|
+
return rb_float_new((dt->jd - newdt->jd) + (dt->nanos - newdt->nanos)/RHR_NANOS_PER_DAYD);
|
1745
|
+
}
|
1746
|
+
}
|
1747
|
+
if (RTEST((rb_obj_is_kind_of(other, rhrd_class)))) {
|
1748
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1749
|
+
Data_Get_Struct(other, rhrd_t, newd);
|
1750
|
+
RHRDT_FILL_JD(dt)
|
1751
|
+
RHRDT_FILL_NANOS(dt)
|
1752
|
+
RHR_FILL_JD(newd)
|
1753
|
+
return rb_float_new((dt->jd - newd->jd) + dt->nanos/RHR_NANOS_PER_DAYD);
|
1754
|
+
}
|
1755
|
+
rb_raise(rb_eTypeError, "expected numeric or date");
|
1756
|
+
}
|
1757
|
+
|
1758
|
+
/* call-seq:
|
1759
|
+
* ===(other) -> true or false
|
1760
|
+
*
|
1761
|
+
* If +other+ is a +Date+, returns +true+ if +other+ is the
|
1762
|
+
* same date as the receiver, or +false+ otherwise.
|
1763
|
+
*
|
1764
|
+
* If +other+ is a +DateTime+, return +true+ if +other has the same
|
1765
|
+
* julian date as the receiver, or +false+ otherwise.
|
1766
|
+
*
|
1767
|
+
* If +other+ is a +Numeric+, convert it to an +Integer+ and return
|
1768
|
+
* +true+ if it is equal to the receiver's julian date, or +false+
|
1769
|
+
* otherwise.
|
1770
|
+
*/
|
1771
|
+
static VALUE rhrdt_op_relationship(VALUE self, VALUE other) {
|
1772
|
+
rhrdt_t *dt, *odt;
|
1773
|
+
rhrd_t *o;
|
1774
|
+
long jd;
|
1775
|
+
|
1776
|
+
if (RTEST(rb_obj_is_kind_of(other, rhrdt_class))) {
|
1777
|
+
Data_Get_Struct(other, rhrdt_t, odt);
|
1778
|
+
RHRDT_FILL_JD(odt)
|
1779
|
+
jd = odt->jd;
|
1780
|
+
} else if (RTEST(rb_obj_is_kind_of(other, rhrd_class))) {
|
1781
|
+
Data_Get_Struct(other, rhrd_t, o);
|
1782
|
+
RHR_FILL_JD(o)
|
1783
|
+
jd = o->jd;
|
1784
|
+
} else if (RTEST((rb_obj_is_kind_of(other, rb_cNumeric)))) {
|
1785
|
+
jd = NUM2LONG(other);
|
1786
|
+
} else {
|
1787
|
+
return Qfalse;
|
1788
|
+
}
|
1789
|
+
|
1790
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1791
|
+
RHRDT_FILL_JD(dt)
|
1792
|
+
return dt->jd == jd ? Qtrue : Qfalse;
|
1793
|
+
}
|
1794
|
+
|
1795
|
+
/* call-seq:
|
1796
|
+
* <=>(other) -> -1, 0, 1, or nil
|
1797
|
+
*
|
1798
|
+
* If +other+ is a +DateTime+, returns -1 if the absolute date and time of
|
1799
|
+
* +other+ is before the absolute time of the receiver chronologically,
|
1800
|
+
* 0 if +other+ is the same absolute date and time as the receiver,
|
1801
|
+
* or 1 if the absolute date and time of +other+ is before the receiver
|
1802
|
+
* chronologically. Absolute date and time in this case means after taking
|
1803
|
+
* account the time zone offset.
|
1804
|
+
*
|
1805
|
+
* If +other+ is a +Date+, return 0 if +other+ has the same
|
1806
|
+
* julian date as the receiver and the receiver has no fractional part,
|
1807
|
+
* 1 if +other+ has a julian date greater than the receiver's, or
|
1808
|
+
* -1 if +other+ has a julian date less than the receiver's or
|
1809
|
+
* a julian date the same as the receiver's and the receiver has a
|
1810
|
+
* fractional part.
|
1811
|
+
*
|
1812
|
+
* If +other+ is a +Numeric+, convert it to an +Float+ and compare
|
1813
|
+
* it to the receiver's julian date plus the fractional part.
|
1814
|
+
*
|
1815
|
+
* For an unrecognized type, return +nil+.
|
1816
|
+
*/
|
1817
|
+
static VALUE rhrdt_op_spaceship(VALUE self, VALUE other) {
|
1818
|
+
rhrdt_t *dt, *odt;
|
1819
|
+
rhrd_t *od;
|
1820
|
+
double diff;
|
1821
|
+
int res;
|
1822
|
+
|
1823
|
+
if (RTEST(rb_obj_is_kind_of(other, rhrdt_class))) {
|
1824
|
+
self = rhrdt__new_offset(self, 0);
|
1825
|
+
other = rhrdt__new_offset(other, 0);
|
1826
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1827
|
+
Data_Get_Struct(other, rhrdt_t, odt);
|
1828
|
+
return LONG2NUM(rhrdt__spaceship(dt, odt));
|
1829
|
+
}
|
1830
|
+
if (RTEST(rb_obj_is_kind_of(other, rhrd_class))) {
|
1831
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1832
|
+
Data_Get_Struct(other, rhrd_t, od);
|
1833
|
+
RHRDT_FILL_JD(dt)
|
1834
|
+
RHR_FILL_JD(od)
|
1835
|
+
RHR_SPACE_SHIP(res, dt->jd, od->jd)
|
1836
|
+
if (res == 0) {
|
1837
|
+
RHRDT_FILL_NANOS(dt)
|
1838
|
+
RHR_SPACE_SHIP(res, dt->nanos, 0)
|
1839
|
+
}
|
1840
|
+
return LONG2NUM(res);
|
1841
|
+
}
|
1842
|
+
if (RTEST((rb_obj_is_kind_of(other, rb_cNumeric)))) {
|
1843
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
1844
|
+
diff = NUM2DBL(other);
|
1845
|
+
RHRDT_FILL_JD(dt)
|
1846
|
+
RHR_SPACE_SHIP(res, dt->jd, (long)diff)
|
1847
|
+
if (res == 0) {
|
1848
|
+
RHRDT_FILL_NANOS(dt)
|
1849
|
+
RHR_SPACE_SHIP(res, dt->nanos, llround((diff - floor(diff)) * RHR_NANOS_PER_DAY))
|
1850
|
+
}
|
1851
|
+
return LONG2NUM(res);
|
1852
|
+
}
|
1853
|
+
return Qnil;
|
1854
|
+
}
|
1855
|
+
|
1856
|
+
#ifdef RUBY19
|
1857
|
+
|
1858
|
+
/* Ruby 1.9 helper methods */
|
1859
|
+
|
1860
|
+
/* Same as rhrd__add_years, but for ruby DateTime values. */
|
1861
|
+
VALUE rhrdt__add_years(VALUE self, long n) {
|
1862
|
+
rhrdt_t *d;
|
1863
|
+
rhrdt_t *newd;
|
1864
|
+
VALUE new;
|
1865
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1866
|
+
|
1867
|
+
new = Data_Make_Struct(rhrdt_class, rhrdt_t, NULL, free, newd);
|
1868
|
+
RHRDT_FILL_CIVIL(d)
|
1869
|
+
memcpy(newd, d, sizeof(rhrdt_t));
|
1870
|
+
|
1871
|
+
newd->year = rhrd__safe_add_long(n, d->year);
|
1872
|
+
if(d->month == 2 && d->day == 29 && !rhrd__leap_year(newd->year)) {
|
1873
|
+
newd->day = 28;
|
1874
|
+
}
|
1875
|
+
|
1876
|
+
RHR_CHECK_CIVIL(newd)
|
1877
|
+
newd->flags &= ~RHR_HAVE_JD;
|
1878
|
+
return new;
|
1879
|
+
}
|
1880
|
+
|
1881
|
+
/* Same as rhrd__day_q, but for ruby DateTime values. */
|
1882
|
+
VALUE rhrdt__day_q(VALUE self, long day) {
|
1883
|
+
rhrdt_t *d;
|
1884
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
1885
|
+
RHRDT_FILL_JD(d)
|
1886
|
+
return rhrd__jd_to_wday(d->jd) == day ? Qtrue : Qfalse;
|
1887
|
+
}
|
1888
|
+
|
1889
|
+
/* Add i given fractional second decimal places to the string,
|
1890
|
+
* starting at the given offset len in the string. */
|
1891
|
+
long rhrdt__add_iso_time_format(rhrdt_t *dt, char *str, long len, long i) {
|
1892
|
+
int l;
|
1893
|
+
|
1894
|
+
RHRDT_FILL_HMS(dt)
|
1895
|
+
|
1896
|
+
if (i < 1) {
|
1897
|
+
i = 0;
|
1898
|
+
} else if (i > 9) {
|
1899
|
+
i = 9;
|
1900
|
+
}
|
1901
|
+
|
1902
|
+
l = snprintf(str + len, 128 - len, "T%02hhi:%02hhi:%02hhi", dt->hour, dt->minute, dt->second);
|
1903
|
+
if (l == -1 || l > 127) {
|
1904
|
+
rb_raise(rb_eNoMemError, "in DateTime formatting method (in snprintf)");
|
1905
|
+
}
|
1906
|
+
len += l;
|
1907
|
+
|
1908
|
+
if (i) {
|
1909
|
+
RHRDT_FILL_NANOS(dt)
|
1910
|
+
l = snprintf(str + len, 128 - len, ".%09lli", dt->nanos % RHR_NANOS_PER_SECOND);
|
1911
|
+
if (l == -1 || l > 127) {
|
1912
|
+
rb_raise(rb_eNoMemError, "in DateTime formatting method (in snprintf)");
|
1913
|
+
}
|
1914
|
+
len += i + 1;
|
1915
|
+
}
|
1916
|
+
|
1917
|
+
l = snprintf(str + len, 128 - len, "%+03i:%02i", dt->offset/60, abs(dt->offset % 60));
|
1918
|
+
if (l == -1 || l > 127) {
|
1919
|
+
rb_raise(rb_eNoMemError, "in DateTime formatting method (in snprintf)");
|
1920
|
+
}
|
1921
|
+
|
1922
|
+
return len + l;
|
1923
|
+
}
|
1924
|
+
|
1925
|
+
/* Ruby 1.9 class methods */
|
1926
|
+
|
1927
|
+
/* call-seq:
|
1928
|
+
* [ruby 1-9 only] <br />
|
1929
|
+
* httpdate() -> DateTime <br />
|
1930
|
+
* httpdate(str, sg=nil) -> DateTime
|
1931
|
+
*
|
1932
|
+
* If no argument is given, returns a +DateTime+ for julian day 0.
|
1933
|
+
* If an argument is given, it should be a string that is
|
1934
|
+
* parsed using +_httpdate+, returning a +DateTime+ or raising
|
1935
|
+
* an +ArgumentError+ if the string is not in a valid format
|
1936
|
+
* or the datetime it represents is not a valid date or time.
|
1937
|
+
* Ignores the 2nd argument.
|
1938
|
+
* Example:
|
1939
|
+
*
|
1940
|
+
* DateTime.httpdate("Fri, 02 Jan 2009 03:04:05 GMT")
|
1941
|
+
* # => #<DateTime 2009-01-02T03:04:05+00:00>
|
1942
|
+
*/
|
1943
|
+
static VALUE rhrdt_s_httpdate(int argc, VALUE *argv, VALUE klass) {
|
1944
|
+
rhrdt_t *d;
|
1945
|
+
VALUE rd;
|
1946
|
+
rd = Data_Make_Struct(klass, rhrdt_t, NULL, free, d);
|
1947
|
+
|
1948
|
+
switch(argc) {
|
1949
|
+
case 0:
|
1950
|
+
d->flags = RHR_HAVE_JD | RHR_HAVE_HMS | RHR_HAVE_NANOS;
|
1951
|
+
return rd;
|
1952
|
+
case 1:
|
1953
|
+
case 2:
|
1954
|
+
rhrdt__fill_from_hash(d, rb_funcall(klass, rhrd_id__httpdate, 1, argv[0]));
|
1955
|
+
return rd;
|
1956
|
+
default:
|
1957
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%i for 2)", argc);
|
1958
|
+
break;
|
1959
|
+
}
|
1960
|
+
}
|
1961
|
+
|
1962
|
+
/* call-seq:
|
1963
|
+
* [ruby 1-9 only] <br />
|
1964
|
+
* iso8601() -> DateTime <br />
|
1965
|
+
* iso8601(str, sg=nil) -> DateTime
|
1966
|
+
*
|
1967
|
+
* If no argument is given, returns a +DateTime+ for julian day 0.
|
1968
|
+
* If an argument is given, it should be a string that is
|
1969
|
+
* parsed using +_iso8601+, returning a +DateTime+ or raising
|
1970
|
+
* an +ArgumentError+ if the string is not in a valid format
|
1971
|
+
* or the datetime it represents is not a valid date or time.
|
1972
|
+
* Ignores the 2nd argument.
|
1973
|
+
* Example:
|
1974
|
+
*
|
1975
|
+
* DateTime.iso8601("2009-01-02T03:04:05+12:00")
|
1976
|
+
* # => #<DateTime 2009-01-02T03:04:05+12:00>
|
1977
|
+
*/
|
1978
|
+
static VALUE rhrdt_s_iso8601(int argc, VALUE *argv, VALUE klass) {
|
1979
|
+
rhrdt_t *d;
|
1980
|
+
VALUE rd;
|
1981
|
+
rd = Data_Make_Struct(klass, rhrdt_t, NULL, free, d);
|
1982
|
+
|
1983
|
+
switch(argc) {
|
1984
|
+
case 0:
|
1985
|
+
d->flags = RHR_HAVE_JD | RHR_HAVE_HMS | RHR_HAVE_NANOS;
|
1986
|
+
return rd;
|
1987
|
+
case 1:
|
1988
|
+
case 2:
|
1989
|
+
rhrdt__fill_from_hash(d, rb_funcall(klass, rhrd_id__iso8601, 1, argv[0]));
|
1990
|
+
return rd;
|
1991
|
+
default:
|
1992
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%i for 2)", argc);
|
1993
|
+
break;
|
1994
|
+
}
|
1995
|
+
}
|
1996
|
+
|
1997
|
+
/* call-seq:
|
1998
|
+
* [ruby 1-9 only] <br />
|
1999
|
+
* jisx0301() -> DateTime <br />
|
2000
|
+
* jisx0301(str, sg=nil) -> DateTime
|
2001
|
+
*
|
2002
|
+
* If no argument is given, returns a +DateTime+ for julian day 0.
|
2003
|
+
* If an argument is given, it should be a string that is
|
2004
|
+
* parsed using +_jisx0301+, returning a +DateTime+ or raising
|
2005
|
+
* an +ArgumentError+ if the string is not in a valid format
|
2006
|
+
* or the datetime it represents is not a valid date or time.
|
2007
|
+
* Ignores the 2nd argument.
|
2008
|
+
* Example:
|
2009
|
+
*
|
2010
|
+
* DateTime.iso8601("H21.01.02T03:04:05+12:00")
|
2011
|
+
* # => #<DateTime 2009-01-02T03:04:05+12:00>
|
2012
|
+
*/
|
2013
|
+
static VALUE rhrdt_s_jisx0301(int argc, VALUE *argv, VALUE klass) {
|
2014
|
+
rhrdt_t *d;
|
2015
|
+
VALUE rd;
|
2016
|
+
rd = Data_Make_Struct(klass, rhrdt_t, NULL, free, d);
|
2017
|
+
|
2018
|
+
switch(argc) {
|
2019
|
+
case 0:
|
2020
|
+
d->flags = RHR_HAVE_JD | RHR_HAVE_HMS | RHR_HAVE_NANOS;
|
2021
|
+
return rd;
|
2022
|
+
case 1:
|
2023
|
+
case 2:
|
2024
|
+
rhrdt__fill_from_hash(d, rb_funcall(klass, rhrd_id__jisx0301, 1, argv[0]));
|
2025
|
+
return rd;
|
2026
|
+
default:
|
2027
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%i for 2)", argc);
|
2028
|
+
break;
|
2029
|
+
}
|
2030
|
+
}
|
2031
|
+
|
2032
|
+
/* call-seq:
|
2033
|
+
* [ruby 1-9 only] <br />
|
2034
|
+
* rfc2822() -> DateTime <br />
|
2035
|
+
* rfc2822(str, sg=nil) -> DateTime
|
2036
|
+
*
|
2037
|
+
* If no argument is given, returns a +DateTime+ for julian day 0.
|
2038
|
+
* If an argument is given, it should be a string that is
|
2039
|
+
* parsed using +_rfc2822+, returning a +DateTime+ or raising
|
2040
|
+
* an +ArgumentError+ if the string is not in a valid format
|
2041
|
+
* or the datetime it represents is not a valid date or time.
|
2042
|
+
* Ignores the 2nd argument.
|
2043
|
+
* Example:
|
2044
|
+
*
|
2045
|
+
* DateTime.rfc2822("Fri, 2 Jan 2009 03:04:05 +1200")
|
2046
|
+
* # => #<DateTime 2009-01-02T03:04:05+12:00>
|
2047
|
+
*/
|
2048
|
+
static VALUE rhrdt_s_rfc2822(int argc, VALUE *argv, VALUE klass) {
|
2049
|
+
rhrdt_t *d;
|
2050
|
+
VALUE rd;
|
2051
|
+
rd = Data_Make_Struct(klass, rhrdt_t, NULL, free, d);
|
2052
|
+
|
2053
|
+
switch(argc) {
|
2054
|
+
case 0:
|
2055
|
+
d->flags = RHR_HAVE_JD | RHR_HAVE_HMS | RHR_HAVE_NANOS;
|
2056
|
+
return rd;
|
2057
|
+
case 1:
|
2058
|
+
case 2:
|
2059
|
+
rhrdt__fill_from_hash(d, rb_funcall(klass, rhrd_id__rfc2822, 1, argv[0]));
|
2060
|
+
return rd;
|
2061
|
+
default:
|
2062
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%i for 2)", argc);
|
2063
|
+
break;
|
2064
|
+
}
|
2065
|
+
}
|
2066
|
+
|
2067
|
+
/* call-seq:
|
2068
|
+
* [ruby 1-9 only] <br />
|
2069
|
+
* rfc3339() -> DateTime <br />
|
2070
|
+
* rfc3339(str, sg=nil) -> DateTime
|
2071
|
+
*
|
2072
|
+
* If no argument is given, returns a +DateTime+ for julian day 0.
|
2073
|
+
* If an argument is given, it should be a string that is
|
2074
|
+
* parsed using +_rfc3339+, returning a +DateTime+ or raising
|
2075
|
+
* an +ArgumentError+ if the string is not in a valid format
|
2076
|
+
* or the datetime it represents is not a valid date or time.
|
2077
|
+
* Ignores the 2nd argument.
|
2078
|
+
* Example:
|
2079
|
+
*
|
2080
|
+
* DateTime.rfc3339("2009-01-02T03:04:05+12:00")
|
2081
|
+
* # => #<DateTime 2009-01-02T03:04:05+12:00>
|
2082
|
+
*/
|
2083
|
+
static VALUE rhrdt_s_rfc3339(int argc, VALUE *argv, VALUE klass) {
|
2084
|
+
rhrdt_t *d;
|
2085
|
+
VALUE rd;
|
2086
|
+
rd = Data_Make_Struct(klass, rhrdt_t, NULL, free, d);
|
2087
|
+
|
2088
|
+
switch(argc) {
|
2089
|
+
case 0:
|
2090
|
+
d->flags = RHR_HAVE_JD | RHR_HAVE_HMS | RHR_HAVE_NANOS;
|
2091
|
+
return rd;
|
2092
|
+
case 1:
|
2093
|
+
case 2:
|
2094
|
+
rhrdt__fill_from_hash(d, rb_funcall(klass, rhrd_id__rfc3339, 1, argv[0]));
|
2095
|
+
return rd;
|
2096
|
+
default:
|
2097
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%i for 2)", argc);
|
2098
|
+
break;
|
2099
|
+
}
|
2100
|
+
}
|
2101
|
+
|
2102
|
+
/* call-seq:
|
2103
|
+
* [ruby 1-9 only] <br />
|
2104
|
+
* xmlschema() -> DateTime <br />
|
2105
|
+
* xmlschema(str, sg=nil) -> DateTime
|
2106
|
+
*
|
2107
|
+
* If no argument is given, returns a +DateTime+ for julian day 0.
|
2108
|
+
* If an argument is given, it should be a string that is
|
2109
|
+
* parsed using +_xmlschema+, returning a +DateTime+ or raising
|
2110
|
+
* an +ArgumentError+ if the string is not in a valid format
|
2111
|
+
* or the datetime it represents is not a valid date or time.
|
2112
|
+
* Ignores the 2nd argument.
|
2113
|
+
* Example:
|
2114
|
+
*
|
2115
|
+
* DateTime.xmlschema("2009-01-02T03:04:05+12:00")
|
2116
|
+
* # => #<DateTime 2009-01-02T03:04:05+12:00>
|
2117
|
+
*/
|
2118
|
+
static VALUE rhrdt_s_xmlschema(int argc, VALUE *argv, VALUE klass) {
|
2119
|
+
rhrdt_t *d;
|
2120
|
+
VALUE rd;
|
2121
|
+
rd = Data_Make_Struct(klass, rhrdt_t, NULL, free, d);
|
2122
|
+
|
2123
|
+
switch(argc) {
|
2124
|
+
case 0:
|
2125
|
+
d->flags = RHR_HAVE_JD | RHR_HAVE_HMS | RHR_HAVE_NANOS;
|
2126
|
+
return rd;
|
2127
|
+
case 1:
|
2128
|
+
case 2:
|
2129
|
+
rhrdt__fill_from_hash(d, rb_funcall(klass, rhrd_id__xmlschema, 1, argv[0]));
|
2130
|
+
return rd;
|
2131
|
+
default:
|
2132
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%i for 2)", argc);
|
2133
|
+
break;
|
2134
|
+
}
|
2135
|
+
}
|
2136
|
+
|
2137
|
+
/* Ruby 1.9 instance methods */
|
2138
|
+
|
2139
|
+
/* call-seq:
|
2140
|
+
* [ruby 1-9 only] <br />
|
2141
|
+
* httpdate() -> String
|
2142
|
+
*
|
2143
|
+
* Returns the receiver as a +String+ in HTTP format. Example:
|
2144
|
+
*
|
2145
|
+
* DateTime.civil(2009, 1, 2, 3, 4, 5).httpdate
|
2146
|
+
* # => "Fri, 02 Jan 2009 03:04:05 GMT"
|
2147
|
+
*/
|
2148
|
+
static VALUE rhrdt_httpdate(VALUE self) {
|
2149
|
+
VALUE s;
|
2150
|
+
rhrdt_t *d;
|
2151
|
+
int len;
|
2152
|
+
s = rhrdt__new_offset(self, 0);
|
2153
|
+
Data_Get_Struct(s, rhrdt_t, d);
|
2154
|
+
RHRDT_FILL_JD(d)
|
2155
|
+
RHRDT_FILL_CIVIL(d)
|
2156
|
+
RHRDT_FILL_HMS(d)
|
2157
|
+
|
2158
|
+
s = rb_str_buf_new(128);
|
2159
|
+
len = snprintf(RSTRING_PTR(s), 128, "%s, %02hhi %s %04li %02hhi:%02hhi:%02hhi GMT",
|
2160
|
+
rhrd__abbr_day_names[rhrd__jd_to_wday(d->jd)],
|
2161
|
+
d->day,
|
2162
|
+
rhrd__abbr_month_names[d->month],
|
2163
|
+
d->year, d->hour, d->minute, d->second);
|
2164
|
+
if (len == -1 || len > 127) {
|
2165
|
+
rb_raise(rb_eNoMemError, "in DateTime#httpdate (in snprintf)");
|
2166
|
+
}
|
2167
|
+
|
2168
|
+
RHR_RETURN_RESIZED_STR(s, len)
|
2169
|
+
}
|
2170
|
+
|
2171
|
+
/* call-seq:
|
2172
|
+
* [ruby 1-9 only] <br />
|
2173
|
+
* iso8601(n=0) -> String
|
2174
|
+
*
|
2175
|
+
* Returns the receiver as a +String+ in ISO8601 format.
|
2176
|
+
* If an argument is given, it should be an +Integer+ representing
|
2177
|
+
* the number of decimal places to use for the fractional seconds.
|
2178
|
+
* Example:
|
2179
|
+
*
|
2180
|
+
* DateTime.civil(2009, 1, 2, 3, 4, 5, 0.5).iso8601
|
2181
|
+
* # => "2009-01-02T03:04:05+12:00"
|
2182
|
+
* DateTime.civil(2009, 1, 2, 3, 4, 5, 0.5).iso8601(4)
|
2183
|
+
* # => "2009-01-02T03:04:05.0000+12:00"
|
2184
|
+
*/
|
2185
|
+
static VALUE rhrdt_iso8601(int argc, VALUE *argv, VALUE self) {
|
2186
|
+
long i;
|
2187
|
+
VALUE s;
|
2188
|
+
rhrdt_t *dt;
|
2189
|
+
char * str;
|
2190
|
+
int len;
|
2191
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
2192
|
+
RHRDT_FILL_CIVIL(dt)
|
2193
|
+
|
2194
|
+
switch(argc) {
|
2195
|
+
case 1:
|
2196
|
+
i = NUM2LONG(argv[0]);
|
2197
|
+
break;
|
2198
|
+
case 0:
|
2199
|
+
i = 0;
|
2200
|
+
break;
|
2201
|
+
default:
|
2202
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
2203
|
+
break;
|
2204
|
+
}
|
2205
|
+
|
2206
|
+
s = rb_str_buf_new(128);
|
2207
|
+
str = RSTRING_PTR(s);
|
2208
|
+
|
2209
|
+
len = snprintf(str, 128, "%04li-%02hhi-%02hhi", dt->year, dt->month, dt->day);
|
2210
|
+
if (len == -1 || len > 127) {
|
2211
|
+
rb_raise(rb_eNoMemError, "in DateTime#to_s (in snprintf)");
|
2212
|
+
}
|
2213
|
+
|
2214
|
+
len = rhrdt__add_iso_time_format(dt, str, len, i);
|
2215
|
+
RHR_RETURN_RESIZED_STR(s, len)
|
2216
|
+
}
|
2217
|
+
|
2218
|
+
/* call-seq:
|
2219
|
+
* [ruby 1-9 only] <br />
|
2220
|
+
* jisx0301(n=0) -> String
|
2221
|
+
*
|
2222
|
+
* Returns the receiver as a +String+ in JIS X 0301 format.
|
2223
|
+
* If an argument is given, it should be an +Integer+ representing
|
2224
|
+
* the number of decimal places to use for the fractional seconds.
|
2225
|
+
* Example:
|
2226
|
+
*
|
2227
|
+
* Date.civil(2009, 1, 2, 3, 4, 5, 0.5).jisx0301
|
2228
|
+
* # => "H21.01.02T03:04:05+12:00"
|
2229
|
+
* Date.civil(2009, 1, 2, 3, 4, 5, 0.5).jisx0301(4)
|
2230
|
+
* # => "H21.01.02T03:04:05.0000+12:00"
|
2231
|
+
*/
|
2232
|
+
static VALUE rhrdt_jisx0301(int argc, VALUE *argv, VALUE self) {
|
2233
|
+
VALUE s;
|
2234
|
+
rhrdt_t *d;
|
2235
|
+
int len;
|
2236
|
+
int i;
|
2237
|
+
char c;
|
2238
|
+
char * str;
|
2239
|
+
long year;
|
2240
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
2241
|
+
RHRDT_FILL_CIVIL(d)
|
2242
|
+
RHRDT_FILL_JD(d)
|
2243
|
+
|
2244
|
+
switch(argc) {
|
2245
|
+
case 1:
|
2246
|
+
i = NUM2LONG(argv[0]);
|
2247
|
+
break;
|
2248
|
+
case 0:
|
2249
|
+
i = 0;
|
2250
|
+
break;
|
2251
|
+
default:
|
2252
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
2253
|
+
break;
|
2254
|
+
}
|
2255
|
+
|
2256
|
+
s = rb_str_buf_new(128);
|
2257
|
+
str = RSTRING_PTR(s);
|
2258
|
+
|
2259
|
+
if (d->jd < 2405160) {
|
2260
|
+
len = snprintf(str, 128, "%04li-%02hhi-%02hhi", d->year, d->month, d->day);
|
2261
|
+
} else {
|
2262
|
+
if (d->jd >= 2447535) {
|
2263
|
+
c = 'H';
|
2264
|
+
year = d->year - 1988;
|
2265
|
+
} else if (d->jd >= 2424875) {
|
2266
|
+
c = 'S';
|
2267
|
+
year = d->year - 1925;
|
2268
|
+
} else if (d->jd >= 2419614) {
|
2269
|
+
c = 'T';
|
2270
|
+
year = d->year - 1911;
|
2271
|
+
} else {
|
2272
|
+
c = 'M';
|
2273
|
+
year = d->year - 1867;
|
2274
|
+
}
|
2275
|
+
len = snprintf(RSTRING_PTR(s), 128, "%c%02li.%02hhi.%02hhi", c, year, d->month, d->day);
|
2276
|
+
}
|
2277
|
+
if (len == -1 || len > 127) {
|
2278
|
+
rb_raise(rb_eNoMemError, "in DateTime#jisx0301 (in snprintf)");
|
2279
|
+
}
|
2280
|
+
|
2281
|
+
len = rhrdt__add_iso_time_format(d, str, len, i);
|
2282
|
+
RHR_RETURN_RESIZED_STR(s, len)
|
2283
|
+
}
|
2284
|
+
|
2285
|
+
/* call-seq:
|
2286
|
+
* [ruby 1-9 only] <br />
|
2287
|
+
* next_day(n=1) -> DateTime
|
2288
|
+
*
|
2289
|
+
* Returns a +DateTime+ +n+ days after the receiver. If +n+ is negative,
|
2290
|
+
* returns a +DateTime+ before the receiver.
|
2291
|
+
* The new +DateTime+ is returned with the same fractional part and offset as the receiver.
|
2292
|
+
*
|
2293
|
+
* DateTime.civil(2009, 1, 2, 12).next_day
|
2294
|
+
* # => #<DateTime 2009-01-03T12:00:00+00:00>
|
2295
|
+
* DateTime.civil(2009, 1, 2, 12).next_day(2)
|
2296
|
+
* # => #<DateTime 2009-01-04T12:00:00+00:00>
|
2297
|
+
*/
|
2298
|
+
static VALUE rhrdt_next_day(int argc, VALUE *argv, VALUE self) {
|
2299
|
+
long i;
|
2300
|
+
|
2301
|
+
switch(argc) {
|
2302
|
+
case 0:
|
2303
|
+
i = 1;
|
2304
|
+
break;
|
2305
|
+
case 1:
|
2306
|
+
i = NUM2LONG(argv[0]);
|
2307
|
+
break;
|
2308
|
+
default:
|
2309
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
2310
|
+
break;
|
2311
|
+
}
|
2312
|
+
|
2313
|
+
return rhrdt__add_days(self, i);
|
2314
|
+
}
|
2315
|
+
|
2316
|
+
/* call-seq:
|
2317
|
+
* [ruby 1-9 only] <br />
|
2318
|
+
* next_month(n=1) -> DateTime
|
2319
|
+
*
|
2320
|
+
* Returns a +DateTime+ +n+ months after the receiver. If +n+ is negative,
|
2321
|
+
* returns a +DateTime+ before the receiver.
|
2322
|
+
* The new +DateTime+ is returned with the same fractional part and offset as the receiver.
|
2323
|
+
*
|
2324
|
+
* DateTime.civil(2009, 1, 2, 12).next_month
|
2325
|
+
* # => #<DateTime 2009-02-02T12:00:00+00:00>
|
2326
|
+
* DateTime.civil(2009, 1, 2, 12).next_month(2)
|
2327
|
+
* # => #<DateTime 2009-03-02T12:00:00+00:00>
|
2328
|
+
*/
|
2329
|
+
static VALUE rhrdt_next_month(int argc, VALUE *argv, VALUE self) {
|
2330
|
+
long i;
|
2331
|
+
|
2332
|
+
switch(argc) {
|
2333
|
+
case 0:
|
2334
|
+
i = 1;
|
2335
|
+
break;
|
2336
|
+
case 1:
|
2337
|
+
i = NUM2LONG(argv[0]);
|
2338
|
+
break;
|
2339
|
+
default:
|
2340
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
2341
|
+
break;
|
2342
|
+
}
|
2343
|
+
|
2344
|
+
return rhrdt__add_months(self, i);
|
2345
|
+
}
|
2346
|
+
|
2347
|
+
/* call-seq:
|
2348
|
+
* [ruby 1-9 only] <br />
|
2349
|
+
* next_year(n=1) -> DateTime
|
2350
|
+
*
|
2351
|
+
* Returns a +DateTime+ +n+ years after the receiver. If +n+ is negative,
|
2352
|
+
* returns a +DateTime+ before the receiver.
|
2353
|
+
* The new +DateTime+ is returned with the same fractional part and offset as the receiver.
|
2354
|
+
*
|
2355
|
+
* DateTime.civil(2009, 1, 2, 12).next_year
|
2356
|
+
* # => #<DateTime 2010-01-02T12:00:00+00:00>
|
2357
|
+
* DateTime.civil(2009, 1, 2, 12).next_year(2)
|
2358
|
+
* # => #<DateTime 2011-01-02T12:00:00+00:00>
|
2359
|
+
*/
|
2360
|
+
static VALUE rhrdt_next_year(int argc, VALUE *argv, VALUE self) {
|
2361
|
+
long i;
|
2362
|
+
|
2363
|
+
switch(argc) {
|
2364
|
+
case 0:
|
2365
|
+
i = 1;
|
2366
|
+
break;
|
2367
|
+
case 1:
|
2368
|
+
i = NUM2LONG(argv[0]);
|
2369
|
+
break;
|
2370
|
+
default:
|
2371
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
2372
|
+
break;
|
2373
|
+
}
|
2374
|
+
|
2375
|
+
return rhrdt__add_years(self, i);
|
2376
|
+
}
|
2377
|
+
|
2378
|
+
/* call-seq:
|
2379
|
+
* [ruby 1-9 only] <br />
|
2380
|
+
* prev_day(n=1) -> DateTime
|
2381
|
+
*
|
2382
|
+
* Returns a +DateTime+ +n+ days before the receiver. If +n+ is negative,
|
2383
|
+
* returns a +DateTime+ after the receiver.
|
2384
|
+
* The new +DateTime+ is returned with the same fractional part and offset as the receiver.
|
2385
|
+
*
|
2386
|
+
* DateTime.civil(2009, 1, 2, 12).prev_day
|
2387
|
+
* # => #<DateTime 2009-01-01T12:00:00+00:00>
|
2388
|
+
* DateTime.civil(2009, 1, 2, 12).prev_day(2)
|
2389
|
+
* # => #<DateTime 2008-12-31T12:00:00+00:00>
|
2390
|
+
*/
|
2391
|
+
static VALUE rhrdt_prev_day(int argc, VALUE *argv, VALUE self) {
|
2392
|
+
long i;
|
2393
|
+
|
2394
|
+
switch(argc) {
|
2395
|
+
case 0:
|
2396
|
+
i = -1;
|
2397
|
+
break;
|
2398
|
+
case 1:
|
2399
|
+
i = -NUM2LONG(argv[0]);
|
2400
|
+
break;
|
2401
|
+
default:
|
2402
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
2403
|
+
break;
|
2404
|
+
}
|
2405
|
+
|
2406
|
+
return rhrdt__add_days(self, i);
|
2407
|
+
}
|
2408
|
+
|
2409
|
+
/* call-seq:
|
2410
|
+
* [ruby 1-9 only] <br />
|
2411
|
+
* prev_month(n=1) -> DateTime
|
2412
|
+
*
|
2413
|
+
* Returns a +DateTime+ +n+ months before the receiver. If +n+ is negative,
|
2414
|
+
* returns a +DateTime+ after the receiver.
|
2415
|
+
* The new +DateTime+ is returned with the same fractional part and offset as the receiver.
|
2416
|
+
*
|
2417
|
+
* DateTime.civil(2009, 1, 2, 12).prev_month
|
2418
|
+
* # => #<DateTime 2008-12-02T12:00:00+00:00>
|
2419
|
+
* DateTime.civil(2009, 1, 2, 12).prev_month(2)
|
2420
|
+
* # => #<DateTime 2008-11-02T12:00:00+00:00>
|
2421
|
+
*/
|
2422
|
+
static VALUE rhrdt_prev_month(int argc, VALUE *argv, VALUE self) {
|
2423
|
+
long i;
|
2424
|
+
|
2425
|
+
switch(argc) {
|
2426
|
+
case 0:
|
2427
|
+
i = -1;
|
2428
|
+
break;
|
2429
|
+
case 1:
|
2430
|
+
i = -NUM2LONG(argv[0]);
|
2431
|
+
break;
|
2432
|
+
default:
|
2433
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
2434
|
+
break;
|
2435
|
+
}
|
2436
|
+
|
2437
|
+
return rhrdt__add_months(self, i);
|
2438
|
+
}
|
2439
|
+
|
2440
|
+
/* call-seq:
|
2441
|
+
* [ruby 1-9 only] <br />
|
2442
|
+
* prev_year(n=1) -> DateTime
|
2443
|
+
*
|
2444
|
+
* Returns a +DateTime+ +n+ years before the receiver. If +n+ is negative,
|
2445
|
+
* returns a +DateTime+ after the receiver.
|
2446
|
+
* The new +DateTime+ is returned with the same fractional part and offset as the receiver.
|
2447
|
+
*
|
2448
|
+
* DateTime.civil(2009, 1, 2, 12).prev_year
|
2449
|
+
* # => #<DateTime 2008-01-02T12:00:00+00:00>
|
2450
|
+
* DateTime.civil(2009, 1, 2, 12).prev_year(2)
|
2451
|
+
* # => #<DateTime 2007-01-02T12:00:00+00:00>
|
2452
|
+
*/
|
2453
|
+
static VALUE rhrdt_prev_year(int argc, VALUE *argv, VALUE self) {
|
2454
|
+
long i;
|
2455
|
+
|
2456
|
+
switch(argc) {
|
2457
|
+
case 0:
|
2458
|
+
i = -1;
|
2459
|
+
break;
|
2460
|
+
case 1:
|
2461
|
+
i = -NUM2LONG(argv[0]);
|
2462
|
+
break;
|
2463
|
+
default:
|
2464
|
+
rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
|
2465
|
+
break;
|
2466
|
+
}
|
2467
|
+
|
2468
|
+
return rhrdt__add_years(self, i);
|
2469
|
+
}
|
2470
|
+
|
2471
|
+
/* call-seq:
|
2472
|
+
* [ruby 1-9 only] <br />
|
2473
|
+
* rfc2822() -> String
|
2474
|
+
*
|
2475
|
+
* Returns the receiver as a +String+ in RFC2822 format. Example:
|
2476
|
+
*
|
2477
|
+
* DateTime.civil(2009, 1, 2, 3, 4, 5, 0.5).rfc2822
|
2478
|
+
* # => "Fri, 2 Jan 2009 03:04:05 +1200"
|
2479
|
+
*/
|
2480
|
+
static VALUE rhrdt_rfc2822(VALUE self) {
|
2481
|
+
VALUE s;
|
2482
|
+
rhrdt_t *d;
|
2483
|
+
int len;
|
2484
|
+
Data_Get_Struct(self, rhrdt_t, d);
|
2485
|
+
RHRDT_FILL_CIVIL(d)
|
2486
|
+
RHRDT_FILL_JD(d)
|
2487
|
+
RHRDT_FILL_HMS(d)
|
2488
|
+
|
2489
|
+
s = rb_str_buf_new(128);
|
2490
|
+
len = snprintf(RSTRING_PTR(s), 128, "%s, %hhi %s %04li %02hhi:%02hhi:%02hhi %+03i%02i",
|
2491
|
+
rhrd__abbr_day_names[rhrd__jd_to_wday(d->jd)],
|
2492
|
+
d->day,
|
2493
|
+
rhrd__abbr_month_names[d->month],
|
2494
|
+
d->year, d->hour, d->minute, d->second, d->offset/60, abs(d->offset % 60));
|
2495
|
+
if (len == -1 || len > 127) {
|
2496
|
+
rb_raise(rb_eNoMemError, "in DateTime#rfc2822 (in snprintf)");
|
2497
|
+
}
|
2498
|
+
|
2499
|
+
RHR_RETURN_RESIZED_STR(s, len)
|
2500
|
+
}
|
2501
|
+
|
2502
|
+
/* call-seq:
|
2503
|
+
* [ruby 1-9 only] <br />
|
2504
|
+
* to_date() -> Date
|
2505
|
+
*
|
2506
|
+
* Returns a +Date+ with the same date as the receiver, ignoring
|
2507
|
+
* any fractional parts or offsets.
|
2508
|
+
*
|
2509
|
+
* DateTime.civil(2009, 1, 2, 12).to_date
|
2510
|
+
* # => #<Date 2009-01-02>
|
2511
|
+
*/
|
2512
|
+
static VALUE rhrdt_to_date(VALUE self) {
|
2513
|
+
rhrd_t *d;
|
2514
|
+
rhrdt_t *dt;
|
2515
|
+
VALUE rd = Data_Make_Struct(rhrd_class, rhrd_t, NULL, free, d);
|
2516
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
2517
|
+
|
2518
|
+
if (RHR_HAS_CIVIL(dt)) {
|
2519
|
+
d->year = dt->year;
|
2520
|
+
d->month = dt->month;
|
2521
|
+
d->day = dt->day;
|
2522
|
+
d->flags |= RHR_HAVE_CIVIL;
|
2523
|
+
}
|
2524
|
+
if (RHR_HAS_JD(dt)) {
|
2525
|
+
d->jd = dt->jd;
|
2526
|
+
d->flags |= RHR_HAVE_JD;
|
2527
|
+
}
|
2528
|
+
|
2529
|
+
return rd;
|
2530
|
+
}
|
2531
|
+
|
2532
|
+
/* call-seq:
|
2533
|
+
* [ruby 1-9 only] <br />
|
2534
|
+
* to_time() -> Time
|
2535
|
+
*
|
2536
|
+
* Returns a +Time+ in local time with the same year, month, day,
|
2537
|
+
* hour, minute, and second as the receiver (in absoute time).
|
2538
|
+
*
|
2539
|
+
* DateTime.civil(2009, 1, 2, 5).to_time
|
2540
|
+
* # => 2009-01-01 21:00:00 -0800
|
2541
|
+
*/
|
2542
|
+
static VALUE rhrdt_to_time(VALUE self) {
|
2543
|
+
long h, m, s;
|
2544
|
+
rhrdt_t *dt;
|
2545
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
2546
|
+
RHRDT_FILL_JD(dt)
|
2547
|
+
RHRDT_FILL_NANOS(dt)
|
2548
|
+
self = rhrdt__from_jd_nanos(dt->jd, dt->nanos - dt->offset * RHR_NANOS_PER_MINUTE, 0);
|
2549
|
+
Data_Get_Struct(self, rhrdt_t, dt);
|
2550
|
+
RHRDT_FILL_CIVIL(dt)
|
2551
|
+
RHRDT_FILL_HMS(dt)
|
2552
|
+
|
2553
|
+
s = dt->nanos/RHR_NANOS_PER_SECOND;
|
2554
|
+
h = s/RHR_SECONDS_PER_HOUR;
|
2555
|
+
m = (s % RHR_SECONDS_PER_HOUR) / 60;
|
2556
|
+
return rb_funcall(rb_funcall(rb_cTime, rhrd_id_utc, 6, LONG2NUM(dt->year), LONG2NUM(dt->month), LONG2NUM(dt->day), LONG2NUM(h), LONG2NUM(m), rb_float_new(s % 60 + (dt->nanos % RHR_NANOS_PER_SECOND)/RHR_NANOS_PER_SECONDD)), rhrd_id_localtime, 0);
|
2557
|
+
}
|
2558
|
+
|
2559
|
+
/* call-seq:
|
2560
|
+
* [ruby 1-9 only] <br />
|
2561
|
+
* to_datetime() -> DateTime
|
2562
|
+
*
|
2563
|
+
* Returns a +DateTime+ with the same year, month, day,
|
2564
|
+
* hour, minute, and second as the receiver in local time.
|
2565
|
+
*
|
2566
|
+
* Time.local(2009, 1, 2, 12).to_datetime
|
2567
|
+
* # => #<DateTime 2009-01-02T12:00:00-08:00>
|
2568
|
+
*/
|
2569
|
+
static VALUE rhrdt_time_to_datetime(VALUE self) {
|
2570
|
+
rhrdt_t *dt;
|
2571
|
+
VALUE rd;
|
2572
|
+
long t, offset;
|
2573
|
+
rd = Data_Make_Struct(rhrdt_class, rhrdt_t, NULL, free, dt);
|
2574
|
+
|
2575
|
+
offset = NUM2LONG(rb_funcall(self, rhrd_id_utc_offset, 0));
|
2576
|
+
t = NUM2LONG(rb_funcall(self, rhrd_id_to_i, 0)) + offset;
|
2577
|
+
dt->jd = rhrd__unix_to_jd(t);
|
2578
|
+
#ifdef RUBY19
|
2579
|
+
dt->nanos = rhrd__mod(t, RHR_SECONDS_PER_DAY) * RHR_NANOS_PER_SECOND + NUM2LONG(rb_funcall(self, rhrd_id_nsec, 0));
|
2580
|
+
#else
|
2581
|
+
dt->nanos = rhrd__mod(t, RHR_SECONDS_PER_DAY) * RHR_NANOS_PER_SECOND + NUM2LONG(rb_funcall(self, rhrd_id_usec, 0)) * 1000;
|
2582
|
+
#endif
|
2583
|
+
dt->offset = offset/60;
|
2584
|
+
dt->flags |= RHR_HAVE_JD | RHR_HAVE_NANOS;
|
2585
|
+
RHR_CHECK_JD(dt);
|
2586
|
+
return rd;
|
2587
|
+
}
|
2588
|
+
|
2589
|
+
/* 1.9 day? instance methods */
|
2590
|
+
|
2591
|
+
/* call-seq:
|
2592
|
+
* [ruby 1-9 only] <br />
|
2593
|
+
* sunday?() -> true or false
|
2594
|
+
*
|
2595
|
+
* Returns +true+ if the receiver is a Sunday, +false+ otherwise.
|
2596
|
+
*/
|
2597
|
+
static VALUE rhrdt_sunday_q(VALUE self) {
|
2598
|
+
return rhrdt__day_q(self, 0);
|
2599
|
+
}
|
2600
|
+
|
2601
|
+
/* call-seq:
|
2602
|
+
* [ruby 1-9 only] <br />
|
2603
|
+
* monday?() -> true or false
|
2604
|
+
*
|
2605
|
+
* Returns +true+ if the receiver is a Monday, +false+ otherwise.
|
2606
|
+
*/
|
2607
|
+
static VALUE rhrdt_monday_q(VALUE self) {
|
2608
|
+
return rhrdt__day_q(self, 1);
|
2609
|
+
}
|
2610
|
+
|
2611
|
+
/* call-seq:
|
2612
|
+
* [ruby 1-9 only] <br />
|
2613
|
+
* tuesday?() -> true or false
|
2614
|
+
*
|
2615
|
+
* Returns +true+ if the receiver is a Tuesday, +false+ otherwise.
|
2616
|
+
*/
|
2617
|
+
static VALUE rhrdt_tuesday_q(VALUE self) {
|
2618
|
+
return rhrdt__day_q(self, 2);
|
2619
|
+
}
|
2620
|
+
|
2621
|
+
/* call-seq:
|
2622
|
+
* [ruby 1-9 only] <br />
|
2623
|
+
* wednesday?() -> true or false
|
2624
|
+
*
|
2625
|
+
* Returns +true+ if the receiver is a Wednesday, +false+ otherwise.
|
2626
|
+
*/
|
2627
|
+
static VALUE rhrdt_wednesday_q(VALUE self) {
|
2628
|
+
return rhrdt__day_q(self, 3);
|
2629
|
+
}
|
2630
|
+
|
2631
|
+
/* call-seq:
|
2632
|
+
* [ruby 1-9 only] <br />
|
2633
|
+
* thursday?() -> true or false
|
2634
|
+
*
|
2635
|
+
* Returns +true+ if the receiver is a Thursday, +false+ otherwise.
|
2636
|
+
*/
|
2637
|
+
static VALUE rhrdt_thursday_q(VALUE self) {
|
2638
|
+
return rhrdt__day_q(self, 4);
|
2639
|
+
}
|
2640
|
+
|
2641
|
+
/* call-seq:
|
2642
|
+
* [ruby 1-9 only] <br />
|
2643
|
+
* friday?() -> true or false
|
2644
|
+
*
|
2645
|
+
* Returns +true+ if the receiver is a Friday, +false+ otherwise.
|
2646
|
+
*/
|
2647
|
+
static VALUE rhrdt_friday_q(VALUE self) {
|
2648
|
+
return rhrdt__day_q(self, 5);
|
2649
|
+
}
|
2650
|
+
|
2651
|
+
/* call-seq:
|
2652
|
+
* [ruby 1-9 only] <br />
|
2653
|
+
* saturday?() -> true or false
|
2654
|
+
*
|
2655
|
+
* Returns +true+ if the receiver is a Saturday, +false+ otherwise.
|
2656
|
+
*/
|
2657
|
+
static VALUE rhrdt_saturday_q(VALUE self) {
|
2658
|
+
return rhrdt__day_q(self, 6);
|
2659
|
+
}
|
2660
|
+
|
2661
|
+
#endif
|
2662
|
+
|
2663
|
+
/* Library initialization */
|
2664
|
+
|
2665
|
+
/* +DateTime+ is used to store a single point in time. It consists of
|
2666
|
+
* three main parts:
|
2667
|
+
*
|
2668
|
+
* * A single date in the gregorian calendar (similar to +Date+)
|
2669
|
+
* * A time component (hour, minute, second, fractional second)
|
2670
|
+
* * A time zone offset in minutes from UTC
|
2671
|
+
*
|
2672
|
+
* In general, +DateTime+ objects are created by calling one of the class
|
2673
|
+
* methods: +civil+, +parse+, +strptime+, +now+. Once created,
|
2674
|
+
* +DateTime+ objects are immutable. Operations that result in a separate
|
2675
|
+
* datetime (such as adding a number of days), always return a new +DateTime+
|
2676
|
+
* object.
|
2677
|
+
* */
|
2678
|
+
void Init_datetime(void) {
|
2679
|
+
|
2680
|
+
/* Define class */
|
2681
|
+
|
2682
|
+
rhrdt_class = rb_define_class("DateTime", rhrd_class);
|
2683
|
+
rb_undef_alloc_func(rhrdt_class);
|
2684
|
+
rhrdt_s_class = rb_singleton_class(rhrdt_class);
|
2685
|
+
|
2686
|
+
/* Define methods for all ruby versions*/
|
2687
|
+
|
2688
|
+
rb_undef(rhrdt_s_class, rb_intern("today"));
|
2689
|
+
rb_define_method(rhrdt_s_class, "_load", rhrdt_s__load, 1);
|
2690
|
+
rb_define_method(rhrdt_s_class, "_strptime", rhrdt_s__strptime, -1);
|
2691
|
+
rb_define_method(rhrdt_s_class, "civil", rhrdt_s_civil, -1);
|
2692
|
+
rb_define_method(rhrdt_s_class, "commercial", rhrdt_s_commercial, -1);
|
2693
|
+
rb_define_method(rhrdt_s_class, "jd", rhrdt_s_jd, -1);
|
2694
|
+
rb_define_method(rhrdt_s_class, "new!", rhrdt_s_new_b, -1);
|
2695
|
+
rb_define_method(rhrdt_s_class, "now", rhrdt_s_now, -1);
|
2696
|
+
rb_define_method(rhrdt_s_class, "ordinal", rhrdt_s_ordinal, -1);
|
2697
|
+
rb_define_method(rhrdt_s_class, "parse", rhrdt_s_parse, -1);
|
2698
|
+
rb_define_method(rhrdt_s_class, "strptime", rhrdt_s_strptime, -1);
|
2699
|
+
|
2700
|
+
rb_define_alias(rhrdt_s_class, "new", "civil");
|
2701
|
+
|
2702
|
+
rb_define_method(rhrdt_class, "_dump", rhrdt__dump, 1);
|
2703
|
+
rb_define_method(rhrdt_class, "ajd", rhrdt_ajd, 0);
|
2704
|
+
rb_define_method(rhrdt_class, "amjd", rhrdt_amjd, 0);
|
2705
|
+
rb_define_method(rhrdt_class, "asctime", rhrdt_asctime, 0);
|
2706
|
+
rb_define_method(rhrdt_class, "cwday", rhrdt_cwday, 0);
|
2707
|
+
rb_define_method(rhrdt_class, "cweek", rhrdt_cweek, 0);
|
2708
|
+
rb_define_method(rhrdt_class, "cwyear", rhrdt_cwyear, 0);
|
2709
|
+
rb_define_method(rhrdt_class, "day", rhrdt_day, 0);
|
2710
|
+
rb_define_method(rhrdt_class, "day_fraction", rhrdt_day_fraction, 0);
|
2711
|
+
rb_define_method(rhrdt_class, "downto", rhrdt_downto, 1);
|
2712
|
+
rb_define_method(rhrdt_class, "eql?", rhrdt_eql_q, 1);
|
2713
|
+
rb_define_method(rhrdt_class, "hash", rhrdt_hash, 0);
|
2714
|
+
rb_define_method(rhrdt_class, "hour", rhrdt_hour, 0);
|
2715
|
+
rb_define_method(rhrdt_class, "inspect", rhrdt_inspect, 0);
|
2716
|
+
rb_define_method(rhrdt_class, "jd", rhrdt_jd, 0);
|
2717
|
+
rb_define_method(rhrdt_class, "ld", rhrdt_ld, 0);
|
2718
|
+
rb_define_method(rhrdt_class, "leap?", rhrdt_leap_q, 0);
|
2719
|
+
rb_define_method(rhrdt_class, "min", rhrdt_min, 0);
|
2720
|
+
rb_define_method(rhrdt_class, "mjd", rhrdt_mjd, 0);
|
2721
|
+
rb_define_method(rhrdt_class, "month", rhrdt_month, 0);
|
2722
|
+
rb_define_method(rhrdt_class, "new_offset", rhrdt_new_offset, -1);
|
2723
|
+
rb_define_method(rhrdt_class, "next", rhrdt_next, 0);
|
2724
|
+
rb_define_method(rhrdt_class, "offset", rhrdt_offset, 0);
|
2725
|
+
rb_define_method(rhrdt_class, "sec", rhrdt_sec, 0);
|
2726
|
+
rb_define_method(rhrdt_class, "sec_fraction", rhrdt_sec_fraction, 0);
|
2727
|
+
rb_define_method(rhrdt_class, "step", rhrdt_step, -1);
|
2728
|
+
rb_define_method(rhrdt_class, "strftime", rhrdt_strftime, -1);
|
2729
|
+
rb_define_method(rhrdt_class, "to_s", rhrdt_to_s, 0);
|
2730
|
+
rb_define_method(rhrdt_class, "upto", rhrdt_upto, 1);
|
2731
|
+
rb_define_method(rhrdt_class, "wday", rhrdt_wday, 0);
|
2732
|
+
rb_define_method(rhrdt_class, "yday", rhrdt_yday, 0);
|
2733
|
+
rb_define_method(rhrdt_class, "year", rhrdt_year, 0);
|
2734
|
+
rb_define_method(rhrdt_class, "zone", rhrdt_zone, 0);
|
2735
|
+
|
2736
|
+
rb_define_method(rhrdt_class, ">>", rhrdt_op_right_shift, 1);
|
2737
|
+
rb_define_method(rhrdt_class, "<<", rhrdt_op_left_shift, 1);
|
2738
|
+
rb_define_method(rhrdt_class, "+", rhrdt_op_plus, 1);
|
2739
|
+
rb_define_method(rhrdt_class, "-", rhrdt_op_minus, 1);
|
2740
|
+
rb_define_method(rhrdt_class, "===", rhrdt_op_relationship, 1);
|
2741
|
+
rb_define_method(rhrdt_class, "<=>", rhrdt_op_spaceship, 1);
|
2742
|
+
|
2743
|
+
rb_define_alias(rhrdt_class, "ctime", "asctime");
|
2744
|
+
rb_define_alias(rhrdt_class, "mday", "day");
|
2745
|
+
rb_define_alias(rhrdt_class, "mon", "month");
|
2746
|
+
rb_define_alias(rhrdt_class, "succ", "next");
|
2747
|
+
|
2748
|
+
#ifdef RUBY19
|
2749
|
+
|
2750
|
+
/* Define methods for ruby 1.9 */
|
2751
|
+
|
2752
|
+
rb_define_method(rhrdt_s_class, "httpdate", rhrdt_s_httpdate, -1);
|
2753
|
+
rb_define_method(rhrdt_s_class, "iso8601", rhrdt_s_iso8601, -1);
|
2754
|
+
rb_define_method(rhrdt_s_class, "jisx0301", rhrdt_s_jisx0301, -1);
|
2755
|
+
rb_define_method(rhrdt_s_class, "rfc2822", rhrdt_s_rfc2822, -1);
|
2756
|
+
rb_define_method(rhrdt_s_class, "rfc3339", rhrdt_s_rfc3339, -1);
|
2757
|
+
rb_define_method(rhrdt_s_class, "xmlschema", rhrdt_s_xmlschema, -1);
|
2758
|
+
|
2759
|
+
rb_define_alias(rhrdt_s_class, "rfc822", "rfc2822");
|
2760
|
+
|
2761
|
+
rb_define_method(rhrdt_class, "httpdate", rhrdt_httpdate, 0);
|
2762
|
+
rb_define_method(rhrdt_class, "iso8601", rhrdt_iso8601, -1);
|
2763
|
+
rb_define_method(rhrdt_class, "jisx0301", rhrdt_jisx0301, -1);
|
2764
|
+
rb_define_method(rhrdt_class, "next_day", rhrdt_next_day, -1);
|
2765
|
+
rb_define_method(rhrdt_class, "next_month", rhrdt_next_month, -1);
|
2766
|
+
rb_define_method(rhrdt_class, "next_year", rhrdt_next_year, -1);
|
2767
|
+
rb_define_method(rhrdt_class, "prev_day", rhrdt_prev_day, -1);
|
2768
|
+
rb_define_method(rhrdt_class, "prev_month", rhrdt_prev_month, -1);
|
2769
|
+
rb_define_method(rhrdt_class, "prev_year", rhrdt_prev_year, -1);
|
2770
|
+
rb_define_method(rhrdt_class, "rfc2822", rhrdt_rfc2822, 0);
|
2771
|
+
rb_define_method(rhrdt_class, "to_date", rhrdt_to_date, 0);
|
2772
|
+
rb_define_method(rhrdt_class, "to_time", rhrdt_to_time, 0);
|
2773
|
+
|
2774
|
+
rb_define_alias(rhrdt_class, "minute", "min");
|
2775
|
+
rb_define_alias(rhrdt_class, "rfc3339", "iso8601");
|
2776
|
+
rb_define_alias(rhrdt_class, "rfc822", "rfc2822");
|
2777
|
+
rb_define_alias(rhrdt_class, "second", "sec");
|
2778
|
+
rb_define_alias(rhrdt_class, "second_fraction", "sec_fraction");
|
2779
|
+
rb_define_alias(rhrdt_class, "to_datetime", "gregorian");
|
2780
|
+
rb_define_alias(rhrdt_class, "xmlschema", "iso8601");
|
2781
|
+
|
2782
|
+
rb_define_method(rhrdt_class, "sunday?", rhrdt_sunday_q, 0);
|
2783
|
+
rb_define_method(rhrdt_class, "monday?", rhrdt_monday_q, 0);
|
2784
|
+
rb_define_method(rhrdt_class, "tuesday?", rhrdt_tuesday_q, 0);
|
2785
|
+
rb_define_method(rhrdt_class, "wednesday?", rhrdt_wednesday_q, 0);
|
2786
|
+
rb_define_method(rhrdt_class, "thursday?", rhrdt_thursday_q, 0);
|
2787
|
+
rb_define_method(rhrdt_class, "friday?", rhrdt_friday_q, 0);
|
2788
|
+
rb_define_method(rhrdt_class, "saturday?", rhrdt_saturday_q, 0);
|
2789
|
+
|
2790
|
+
rb_define_method(rb_cTime, "to_datetime", rhrdt_time_to_datetime, 0);
|
2791
|
+
#else
|
2792
|
+
|
2793
|
+
/* Define methods for ruby 1.8 */
|
2794
|
+
|
2795
|
+
rb_define_alias(rhrdt_s_class, "new0", "new!");
|
2796
|
+
rb_define_alias(rhrdt_s_class, "new1", "jd");
|
2797
|
+
rb_define_alias(rhrdt_s_class, "new2", "ordinal");
|
2798
|
+
rb_define_alias(rhrdt_s_class, "new3", "civil");
|
2799
|
+
rb_define_alias(rhrdt_s_class, "neww", "commercial");
|
2800
|
+
|
2801
|
+
rb_define_alias(rhrdt_class, "newof", "new_offset");
|
2802
|
+
rb_define_alias(rhrdt_class, "of", "offset");
|
2803
|
+
#endif
|
2804
|
+
}
|