rhodes-framework 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.gitignore +2 -0
  2. data/History.txt +37 -0
  3. data/Manifest.txt +66 -0
  4. data/README.rdoc +2 -0
  5. data/Rakefile +50 -0
  6. data/lib/ServeME.rb +7 -0
  7. data/lib/TestServe.rb +9 -0
  8. data/lib/bsearch.rb +120 -0
  9. data/lib/builtinME.rb +626 -0
  10. data/lib/date/format.rb +1339 -0
  11. data/lib/date.rb +1792 -0
  12. data/lib/dateME.rb +24 -0
  13. data/lib/erb.rb +896 -0
  14. data/lib/find.rb +81 -0
  15. data/lib/rational.rb +19 -0
  16. data/lib/rationalME.rb +530 -0
  17. data/lib/rho/render.rb +51 -0
  18. data/lib/rho/rho.rb +255 -0
  19. data/lib/rho/rhoapplication.rb +36 -0
  20. data/lib/rho/rhocontact.rb +110 -0
  21. data/lib/rho/rhocontroller.rb +35 -0
  22. data/lib/rho/rhofsconnector.rb +32 -0
  23. data/lib/rho/rhosupport.rb +146 -0
  24. data/lib/rho/rhoviewhelpers.rb +130 -0
  25. data/lib/rho.rb +1 -0
  26. data/lib/rhodes-framework.rb +2 -0
  27. data/lib/rhodes.rb +9 -0
  28. data/lib/rhoframework.rb +38 -0
  29. data/lib/rhofsconnector.rb +1 -0
  30. data/lib/rhom/rhom.rb +58 -0
  31. data/lib/rhom/rhom_db_adapter.rb +185 -0
  32. data/lib/rhom/rhom_db_adapterME.rb +93 -0
  33. data/lib/rhom/rhom_object.rb +69 -0
  34. data/lib/rhom/rhom_object_factory.rb +309 -0
  35. data/lib/rhom/rhom_source.rb +60 -0
  36. data/lib/rhom.rb +1 -0
  37. data/lib/singleton.rb +137 -0
  38. data/lib/time.rb +489 -0
  39. data/lib/version.rb +8 -0
  40. data/res/sqlite3/constants.rb +49 -0
  41. data/res/sqlite3/database.rb +715 -0
  42. data/res/sqlite3/driver/dl/api.rb +154 -0
  43. data/res/sqlite3/driver/dl/driver.rb +307 -0
  44. data/res/sqlite3/driver/native/driver.rb +257 -0
  45. data/res/sqlite3/errors.rb +68 -0
  46. data/res/sqlite3/pragmas.rb +271 -0
  47. data/res/sqlite3/resultset.rb +176 -0
  48. data/res/sqlite3/sqlite3_api.rb +0 -0
  49. data/res/sqlite3/statement.rb +230 -0
  50. data/res/sqlite3/translator.rb +109 -0
  51. data/res/sqlite3/value.rb +57 -0
  52. data/res/sqlite3/version.rb +14 -0
  53. data/rhodes-framework.gemspec +18 -0
  54. data/rhodes.gemspec +18 -0
  55. data/spec/app_manifest.txt +4 -0
  56. data/spec/configs/account.rb +3 -0
  57. data/spec/configs/case.rb +3 -0
  58. data/spec/configs/employee.rb +3 -0
  59. data/spec/rho_controller_spec.rb +144 -0
  60. data/spec/rho_spec.rb +75 -0
  61. data/spec/rhom_object_factory_spec.rb +372 -0
  62. data/spec/rhom_spec.rb +45 -0
  63. data/spec/spec.opts +1 -0
  64. data/spec/spec_helper.rb +49 -0
  65. data/spec/stubs.rb +39 -0
  66. data/spec/syncdbtest.sqlite +0 -0
  67. metadata +202 -0
@@ -0,0 +1,1339 @@
1
+ # format.rb: Written by Tadayoshi Funaba 1999-2008
2
+ # $Id: format.rb,v 2.43 2008-01-17 20:16:31+09 tadf Exp $
3
+
4
+ if defined? RHO_ME
5
+ require 'rationalME'
6
+ end
7
+
8
+ require 'rational'
9
+
10
+ class Date
11
+
12
+ #SECONDS_IN_DAY = 60*60*24
13
+ #SECONDS_IN_DAY = Rational(1, 86400)
14
+
15
+ #From date.rb:
16
+ # Full month names, in English. Months count from 1 to 12; a
17
+ # month's numerical representation indexed into this array
18
+ # gives the name of that month (hence the first element is nil).
19
+ MONTHNAMES = [nil] + %w(January February March April May June July
20
+ August September October November December)
21
+
22
+ # Full names of days of the week, in English. Days of the week
23
+ # count from 0 to 6 (except in the commercial week); a day's numerical
24
+ # representation indexed into this array gives the name of that day.
25
+ DAYNAMES = %w(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
26
+
27
+ # Abbreviated month names, in English.
28
+ ABBR_MONTHNAMES = [nil] + %w(Jan Feb Mar Apr May Jun
29
+ Jul Aug Sep Oct Nov Dec)
30
+ # Abbreviated day names, in English.
31
+ ABBR_DAYNAMES = %w(Sun Mon Tue Wed Thu Fri Sat)
32
+
33
+ module Format # :nodoc:
34
+
35
+
36
+ MONTHS = {
37
+ 'january' => 1, 'february' => 2, 'march' => 3, 'april' => 4,
38
+ 'may' => 5, 'june' => 6, 'july' => 7, 'august' => 8,
39
+ 'september'=> 9, 'october' =>10, 'november' =>11, 'december' =>12
40
+ }
41
+
42
+ DAYS = {
43
+ 'sunday' => 0, 'monday' => 1, 'tuesday' => 2, 'wednesday'=> 3,
44
+ 'thursday' => 4, 'friday' => 5, 'saturday' => 6
45
+ }
46
+
47
+ ABBR_MONTHS = {
48
+ 'jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4,
49
+ 'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8,
50
+ 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12
51
+ }
52
+
53
+ ABBR_DAYS = {
54
+ 'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3,
55
+ 'thu' => 4, 'fri' => 5, 'sat' => 6
56
+ }
57
+
58
+ ZONES = {
59
+ 'ut' => 0*3600, 'gmt' => 0*3600, 'est' => -5*3600, 'edt' => -4*3600,
60
+ 'cst' => -6*3600, 'cdt' => -5*3600, 'mst' => -7*3600, 'mdt' => -6*3600,
61
+ 'pst' => -8*3600, 'pdt' => -7*3600,
62
+ 'a' => 1*3600, 'b' => 2*3600, 'c' => 3*3600, 'd' => 4*3600,
63
+ 'e' => 5*3600, 'f' => 6*3600, 'g' => 7*3600, 'h' => 8*3600,
64
+ 'i' => 9*3600, 'k' => 10*3600, 'l' => 11*3600, 'm' => 12*3600,
65
+ 'n' => -1*3600, 'o' => -2*3600, 'p' => -3*3600, 'q' => -4*3600,
66
+ 'r' => -5*3600, 's' => -6*3600, 't' => -7*3600, 'u' => -8*3600,
67
+ 'v' => -9*3600, 'w' =>-10*3600, 'x' =>-11*3600, 'y' =>-12*3600,
68
+ 'z' => 0*3600,
69
+
70
+ 'utc' => 0*3600, 'wet' => 0*3600,
71
+ 'at' => -2*3600, 'brst'=> -2*3600, 'ndt' => -(2*3600+1800),
72
+ 'art' => -3*3600, 'adt' => -3*3600, 'brt' => -3*3600, 'clst'=> -3*3600,
73
+ 'nst' => -(3*3600+1800),
74
+ 'ast' => -4*3600, 'clt' => -4*3600,
75
+ 'akdt'=> -8*3600, 'ydt' => -8*3600,
76
+ 'akst'=> -9*3600, 'hadt'=> -9*3600, 'hdt' => -9*3600, 'yst' => -9*3600,
77
+ 'ahst'=>-10*3600, 'cat' =>-10*3600, 'hast'=>-10*3600, 'hst' =>-10*3600,
78
+ 'nt' =>-11*3600,
79
+ 'idlw'=>-12*3600,
80
+ 'bst' => 1*3600, 'cet' => 1*3600, 'fwt' => 1*3600, 'met' => 1*3600,
81
+ 'mewt'=> 1*3600, 'mez' => 1*3600, 'swt' => 1*3600, 'wat' => 1*3600,
82
+ 'west'=> 1*3600,
83
+ 'cest'=> 2*3600, 'eet' => 2*3600, 'fst' => 2*3600, 'mest'=> 2*3600,
84
+ 'mesz'=> 2*3600, 'sast'=> 2*3600, 'sst' => 2*3600,
85
+ 'bt' => 3*3600, 'eat' => 3*3600, 'eest'=> 3*3600, 'msk' => 3*3600,
86
+ 'msd' => 4*3600, 'zp4' => 4*3600,
87
+ 'zp5' => 5*3600, 'ist' => (5*3600+1800),
88
+ 'zp6' => 6*3600,
89
+ 'wast'=> 7*3600,
90
+ 'cct' => 8*3600, 'sgt' => 8*3600, 'wadt'=> 8*3600,
91
+ 'jst' => 9*3600, 'kst' => 9*3600,
92
+ 'east'=> 10*3600, 'gst' => 10*3600,
93
+ 'eadt'=> 11*3600,
94
+ 'idle'=> 12*3600, 'nzst'=> 12*3600, 'nzt' => 12*3600,
95
+ 'nzdt'=> 13*3600,
96
+
97
+ 'afghanistan' => 16200, 'alaskan' => -32400,
98
+ 'arab' => 10800, 'arabian' => 14400,
99
+ 'arabic' => 10800, 'atlantic' => -14400,
100
+ 'aus central' => 34200, 'aus eastern' => 36000,
101
+ 'azores' => -3600, 'canada central' => -21600,
102
+ 'cape verde' => -3600, 'caucasus' => 14400,
103
+ 'cen. australia' => 34200, 'central america' => -21600,
104
+ 'central asia' => 21600, 'central europe' => 3600,
105
+ 'central european' => 3600, 'central pacific' => 39600,
106
+ 'central' => -21600, 'china' => 28800,
107
+ 'dateline' => -43200, 'e. africa' => 10800,
108
+ 'e. australia' => 36000, 'e. europe' => 7200,
109
+ 'e. south america' => -10800, 'eastern' => -18000,
110
+ 'egypt' => 7200, 'ekaterinburg' => 18000,
111
+ 'fiji' => 43200, 'fle' => 7200,
112
+ 'greenland' => -10800, 'greenwich' => 0,
113
+ 'gtb' => 7200, 'hawaiian' => -36000,
114
+ 'india' => 19800, 'iran' => 12600,
115
+ 'jerusalem' => 7200, 'korea' => 32400,
116
+ 'mexico' => -21600, 'mid-atlantic' => -7200,
117
+ 'mountain' => -25200, 'myanmar' => 23400,
118
+ 'n. central asia' => 21600, 'nepal' => 20700,
119
+ 'new zealand' => 43200, 'newfoundland' => -12600,
120
+ 'north asia east' => 28800, 'north asia' => 25200,
121
+ 'pacific sa' => -14400, 'pacific' => -28800,
122
+ 'romance' => 3600, 'russian' => 10800,
123
+ 'sa eastern' => -10800, 'sa pacific' => -18000,
124
+ 'sa western' => -14400, 'samoa' => -39600,
125
+ 'se asia' => 25200, 'malay peninsula' => 28800,
126
+ 'south africa' => 7200, 'sri lanka' => 21600,
127
+ 'taipei' => 28800, 'tasmania' => 36000,
128
+ 'tokyo' => 32400, 'tonga' => 46800,
129
+ 'us eastern' => -18000, 'us mountain' => -25200,
130
+ 'vladivostok' => 36000, 'w. australia' => 28800,
131
+ 'w. central africa' => 3600, 'w. europe' => 3600,
132
+ 'west asia' => 18000, 'west pacific' => 36000,
133
+ 'yakutsk' => 32400
134
+ }
135
+
136
+ [MONTHS, DAYS, ABBR_MONTHS, ABBR_DAYS, ZONES].each do |x|
137
+ x.freeze
138
+ end
139
+
140
+ class Bag # :nodoc:
141
+
142
+ def initialize
143
+ @elem = {}
144
+ end
145
+
146
+ def method_missing(t, *args, &block)
147
+ t = t.to_s
148
+ set = t.chomp!('=')
149
+ t = t.intern
150
+ if set
151
+ @elem[t] = args[0]
152
+ else
153
+ @elem[t]
154
+ end
155
+ end
156
+
157
+ def to_hash
158
+ @elem.reject{|k, v| /\A_/ =~ k.to_s || v.nil?}
159
+ end
160
+
161
+ end
162
+
163
+ end
164
+
165
+ def emit(e, f) # :nodoc:
166
+ case e
167
+ when Numeric
168
+ sign = %w(+ + -)[e <=> 0]
169
+ e = e.abs
170
+ end
171
+
172
+ s = e.to_s
173
+
174
+ if f[:s] && f[:p] == '0'
175
+ f[:w] -= 1
176
+ end
177
+
178
+ if f[:s] && f[:p] == "\s"
179
+ s[0,0] = sign
180
+ end
181
+
182
+ if f[:p] != '-'
183
+ s = s.rjust(f[:w], f[:p])
184
+ end
185
+
186
+ if f[:s] && f[:p] != "\s"
187
+ s[0,0] = sign
188
+ end
189
+
190
+ s = s.upcase if f[:u]
191
+ s = s.downcase if f[:d]
192
+ s
193
+ end
194
+
195
+ def emit_w(e, w, f) # :nodoc:
196
+ f[:w] = [f[:w], w].compact.max
197
+ emit(e, f)
198
+ end
199
+
200
+ def emit_n(e, w, f) # :nodoc:
201
+ f[:p] ||= '0'
202
+ emit_w(e, w, f)
203
+ end
204
+
205
+ def emit_sn(e, w, f) # :nodoc:
206
+ if e < 0
207
+ w += 1
208
+ f[:s] = true
209
+ end
210
+ emit_n(e, w, f)
211
+ end
212
+
213
+ def emit_z(e, w, f) # :nodoc:
214
+ w += 1
215
+ f[:s] = true
216
+ emit_n(e, w, f)
217
+ end
218
+
219
+ def emit_a(e, w, f) # :nodoc:
220
+ f[:p] ||= "\s"
221
+ emit_w(e, w, f)
222
+ end
223
+
224
+ def emit_ad(e, w, f) # :nodoc:
225
+ if f[:x]
226
+ f[:u] = true
227
+ f[:d] = false
228
+ end
229
+ emit_a(e, w, f)
230
+ end
231
+
232
+ def emit_au(e, w, f) # :nodoc:
233
+ if f[:x]
234
+ f[:u] = false
235
+ f[:d] = true
236
+ end
237
+ emit_a(e, w, f)
238
+ end
239
+
240
+ private :emit, :emit_w, :emit_n, :emit_sn, :emit_z,
241
+ :emit_a, :emit_ad, :emit_au
242
+
243
+ def strftime(fmt='%F')
244
+ fmt.gsub(/%([-_0^#]+)?(\d+)?([EO]?(?::{1,3}z|.))/m) do
245
+ f = {}
246
+ m = $&
247
+ s, w, c = $1, $2, $3
248
+ if s
249
+ s.scan(/./) do |k|
250
+ case k
251
+ when '-'; f[:p] = '-'
252
+ when '_'; f[:p] = "\s"
253
+ when '0'; f[:p] = '0'
254
+ when '^'; f[:u] = true
255
+ when '#'; f[:x] = true
256
+ end
257
+ end
258
+ end
259
+ if w
260
+ f[:w] = w.to_i
261
+ end
262
+ case c
263
+ when 'A'; emit_ad(DAYNAMES[wday], 0, f)
264
+ when 'a'; emit_ad(ABBR_DAYNAMES[wday], 0, f)
265
+ when 'B'; emit_ad(MONTHNAMES[mon], 0, f)
266
+ when 'b'; emit_ad(ABBR_MONTHNAMES[mon], 0, f)
267
+ when 'C', 'EC'; emit_sn((year / 100).floor, 2, f)
268
+ when 'c', 'Ec'; emit_a(strftime('%a %b %e %H:%M:%S %Y'), 0, f)
269
+ when 'D'; emit_a(strftime('%m/%d/%y'), 0, f)
270
+ when 'd', 'Od'; emit_n(mday(), 2, f)
271
+ when 'e', 'Oe'; emit_a(mday(), 2, f)
272
+ when 'F'
273
+ if m == '%F'
274
+ format('%.4d-%02d-%02d', year(), mon(), mday()) # 4p
275
+ else
276
+ emit_a(strftime('%Y-%m-%d'), 0, f)
277
+ end
278
+ when 'G'; emit_sn(cwyear(), 4, f)
279
+ when 'g'; emit_n(cwyear % 100, 2, f)
280
+ when 'H', 'OH'; emit_n(hour(), 2, f)
281
+ when 'h'; emit_ad(strftime('%b'), 0, f)
282
+ when 'I', 'OI'; emit_n((hour % 12).nonzero? || 12, 2, f)
283
+ when 'j'; emit_n(yday(), 3, f)
284
+ when 'k'; emit_a(hour(), 2, f)
285
+ when 'L'
286
+ w = f[:w] || 3
287
+ u = 10**w
288
+ emit_n((sec_fraction * u).floor, w, f)
289
+ when 'l'; emit_a((hour % 12).nonzero? || 12, 2, f)
290
+ when 'M', 'OM'; emit_n(min(), 2, f)
291
+ when 'm', 'Om'; emit_n(mon(), 2, f)
292
+ when 'N'
293
+ w = f[:w] || 9
294
+ u = 10**w
295
+ emit_n((sec_fraction * u).floor, w, f)
296
+ when 'n'; emit_a("\n", 0, f)
297
+ when 'P'; emit_ad(strftime('%p').downcase, 0, f)
298
+ when 'p'; emit_au(if hour < 12 then 'AM' else 'PM' end, 0, f)
299
+ when 'Q'
300
+ s = ((ajd - UNIX_EPOCH_IN_AJD) / MILLISECONDS_IN_DAY).round
301
+ emit_sn(s, 1, f)
302
+ when 'R'; emit_a(strftime('%H:%M'), 0, f)
303
+ when 'r'; emit_a(strftime('%I:%M:%S %p'), 0, f)
304
+ when 'S', 'OS'; emit_n(sec(), 2, f)
305
+ when 's'
306
+ s = ((ajd - UNIX_EPOCH_IN_AJD) / Rational(1, 86400)).round
307
+ emit_sn(s, 1, f)
308
+ when 'T'
309
+ if m == '%T'
310
+ format('%02d:%02d:%02d', hour(), min(), sec()) # 4p
311
+ else
312
+ emit_a(strftime('%H:%M:%S'), 0, f)
313
+ end
314
+ when 't'; emit_a("\t", 0, f)
315
+ when 'U', 'W', 'OU', 'OW'
316
+ emit_n(if c[-1,1] == 'U' then wnum0 else wnum1 end, 2, f)
317
+ when 'u', 'Ou'; emit_n(cwday(), 1, f)
318
+ when 'V', 'OV'; emit_n(cweek(), 2, f)
319
+ when 'v'; emit_a(strftime('%e-%b-%Y'), 0, f)
320
+ when 'w', 'Ow'; emit_n(wday(), 1, f)
321
+ when 'X', 'EX'; emit_a(strftime('%H:%M:%S'), 0, f)
322
+ when 'x', 'Ex'; emit_a(strftime('%m/%d/%y'), 0, f)
323
+ when 'Y', 'EY'; emit_sn(year(), 4, f)
324
+ when 'y', 'Ey', 'Oy'; emit_n(year % 100, 2, f)
325
+ when 'Z'; emit_au(strftime('%:z'), 0, f)
326
+ when /\A(:{0,3})z/
327
+ t = $1.size
328
+ sign = if offset < 0 then -1 else +1 end
329
+ fr = offset.abs
330
+ ss = fr.div(Rational(1, 86400)) # 4p
331
+ hh, ss = ss.divmod(3600)
332
+ mm, ss = ss.divmod(60)
333
+ if t == 3
334
+ if ss.nonzero? then t = 2
335
+ elsif mm.nonzero? then t = 1
336
+ else t = -1
337
+ end
338
+ end
339
+ case t
340
+ when -1
341
+ tail = []
342
+ sep = ''
343
+ when 0
344
+ f[:w] -= 2 if f[:w]
345
+ tail = ['%02d' % mm]
346
+ sep = ''
347
+ when 1
348
+ f[:w] -= 3 if f[:w]
349
+ tail = ['%02d' % mm]
350
+ sep = ':'
351
+ when 2
352
+ f[:w] -= 6 if f[:w]
353
+ tail = ['%02d' % mm, '%02d' % ss]
354
+ sep = ':'
355
+ end
356
+ ([emit_z(sign * hh, 2, f)] + tail).join(sep)
357
+ when '%'; emit_a('%', 0, f)
358
+ when '+'; emit_a(strftime('%a %b %e %H:%M:%S %Z %Y'), 0, f)
359
+ else
360
+ m
361
+ end
362
+ end
363
+ end
364
+
365
+ # alias_method :format, :strftime
366
+
367
+ def asctime() strftime('%c') end
368
+
369
+ alias_method :ctime, :asctime
370
+
371
+ def iso8601() strftime('%F') end
372
+
373
+ def rfc3339() iso8601 end
374
+
375
+ def xmlschema() iso8601 end # :nodoc:
376
+
377
+ def rfc2822() strftime('%a, %-d %b %Y %T %z') end
378
+
379
+ alias_method :rfc822, :rfc2822
380
+
381
+ def httpdate() new_offset(0).strftime('%a, %d %b %Y %T GMT') end # :nodoc:
382
+
383
+ def jisx0301
384
+ if jd < 2405160
385
+ iso8601
386
+ else
387
+ case jd
388
+ when 2405160...2419614
389
+ g = 'M%02d' % (year - 1867)
390
+ when 2419614...2424875
391
+ g = 'T%02d' % (year - 1911)
392
+ when 2424875...2447535
393
+ g = 'S%02d' % (year - 1925)
394
+ else
395
+ g = 'H%02d' % (year - 1988)
396
+ end
397
+ g + strftime('.%m.%d')
398
+ end
399
+ end
400
+
401
+ =begin
402
+ def beat(n=0)
403
+ i, f = (new_offset(HOURS_IN_DAY).day_fraction * 1000).divmod(1)
404
+ ('@%03d' % i) +
405
+ if n < 1
406
+ ''
407
+ else
408
+ '.%0*d' % [n, (f / Rational(1, 10**n)).round]
409
+ end
410
+ end
411
+ =end
412
+
413
+ def self.num_pattern? (s) # :nodoc:
414
+ /\A%[EO]?[CDdeFGgHIjkLlMmNQRrSsTUuVvWwXxYy\d]/ =~ s || /\A\d/ =~ s
415
+ end
416
+
417
+ private_class_method :num_pattern?
418
+
419
+ def self._strptime_i(str, fmt, e) # :nodoc:
420
+ fmt.scan(/%([EO]?(?::{1,3}z|.))|(.)/m) do |s, c|
421
+ a = $&
422
+ if s
423
+ case s
424
+ when 'A', 'a'
425
+ return unless str.sub!(/\A(#{Format::DAYS.keys.join('|')})/io, '') ||
426
+ str.sub!(/\A(#{Format::ABBR_DAYS.keys.join('|')})/io, '')
427
+ val = Format::DAYS[$1.downcase] || Format::ABBR_DAYS[$1.downcase]
428
+ return unless val
429
+ e.wday = val
430
+ when 'B', 'b', 'h'
431
+ return unless str.sub!(/\A(#{Format::MONTHS.keys.join('|')})/io, '') ||
432
+ str.sub!(/\A(#{Format::ABBR_MONTHS.keys.join('|')})/io, '')
433
+ val = Format::MONTHS[$1.downcase] || Format::ABBR_MONTHS[$1.downcase]
434
+ return unless val
435
+ e.mon = val
436
+ when 'C', 'EC'
437
+ return unless str.sub!(if num_pattern?($')
438
+ then /\A([-+]?\d{1,2})/
439
+ else /\A([-+]?\d{1,})/
440
+ end, '')
441
+ val = $1.to_i
442
+ e._cent = val
443
+ when 'c', 'Ec'
444
+ return unless _strptime_i(str, '%a %b %e %H:%M:%S %Y', e)
445
+ when 'D'
446
+ return unless _strptime_i(str, '%m/%d/%y', e)
447
+ when 'd', 'e', 'Od', 'Oe'
448
+ return unless str.sub!(/\A( \d|\d{1,2})/, '')
449
+ val = $1.to_i
450
+ return unless (1..31) === val
451
+ e.mday = val
452
+ when 'F'
453
+ return unless _strptime_i(str, '%Y-%m-%d', e)
454
+ when 'G'
455
+ return unless str.sub!(if num_pattern?($')
456
+ then /\A([-+]?\d{1,4})/
457
+ else /\A([-+]?\d{1,})/
458
+ end, '')
459
+ val = $1.to_i
460
+ e.cwyear = val
461
+ when 'g'
462
+ return unless str.sub!(/\A(\d{1,2})/, '')
463
+ val = $1.to_i
464
+ return unless (0..99) === val
465
+ e.cwyear = val
466
+ e._cent ||= if val >= 69 then 19 else 20 end
467
+ when 'H', 'k', 'OH'
468
+ return unless str.sub!(/\A( \d|\d{1,2})/, '')
469
+ val = $1.to_i
470
+ return unless (0..24) === val
471
+ e.hour = val
472
+ when 'I', 'l', 'OI'
473
+ return unless str.sub!(/\A( \d|\d{1,2})/, '')
474
+ val = $1.to_i
475
+ return unless (1..12) === val
476
+ e.hour = val
477
+ when 'j'
478
+ return unless str.sub!(/\A(\d{1,3})/, '')
479
+ val = $1.to_i
480
+ return unless (1..366) === val
481
+ e.yday = val
482
+ when 'L'
483
+ return unless str.sub!(if num_pattern?($')
484
+ then /\A([-+]?\d{1,3})/
485
+ else /\A([-+]?\d{1,})/
486
+ end, '')
487
+ # val = Rational($1.to_i, 10**3)
488
+ val = Rational($1.to_i, 10**$1.size)
489
+ e.sec_fraction = val
490
+ when 'M', 'OM'
491
+ return unless str.sub!(/\A(\d{1,2})/, '')
492
+ val = $1.to_i
493
+ return unless (0..59) === val
494
+ e.min = val
495
+ when 'm', 'Om'
496
+ return unless str.sub!(/\A(\d{1,2})/, '')
497
+ val = $1.to_i
498
+ return unless (1..12) === val
499
+ e.mon = val
500
+ when 'N'
501
+ return unless str.sub!(if num_pattern?($')
502
+ then /\A([-+]?\d{1,9})/
503
+ else /\A([-+]?\d{1,})/
504
+ end, '')
505
+ # val = Rational($1.to_i, 10**9)
506
+ val = Rational($1.to_i, 10**$1.size)
507
+ e.sec_fraction = val
508
+ when 'n', 't'
509
+ return unless _strptime_i(str, "\s", e)
510
+ when 'P', 'p'
511
+ return unless str.sub!(/\A([ap])(?:m\b|\.m\.)/i, '')
512
+ e._merid = if $1.downcase == 'a' then 0 else 12 end
513
+ when 'Q'
514
+ return unless str.sub!(/\A(-?\d{1,})/, '')
515
+ val = Rational($1.to_i, 10**3)
516
+ e.seconds = val
517
+ when 'R'
518
+ return unless _strptime_i(str, '%H:%M', e)
519
+ when 'r'
520
+ return unless _strptime_i(str, '%I:%M:%S %p', e)
521
+ when 'S', 'OS'
522
+ return unless str.sub!(/\A(\d{1,2})/, '')
523
+ val = $1.to_i
524
+ return unless (0..60) === val
525
+ e.sec = val
526
+ when 's'
527
+ return unless str.sub!(/\A(-?\d{1,})/, '')
528
+ val = $1.to_i
529
+ e.seconds = val
530
+ when 'T'
531
+ return unless _strptime_i(str, '%H:%M:%S', e)
532
+ when 'U', 'W', 'OU', 'OW'
533
+ return unless str.sub!(/\A(\d{1,2})/, '')
534
+ val = $1.to_i
535
+ return unless (0..53) === val
536
+ e.__send__(if s[-1,1] == 'U' then :wnum0= else :wnum1= end, val)
537
+ when 'u', 'Ou'
538
+ return unless str.sub!(/\A(\d{1})/, '')
539
+ val = $1.to_i
540
+ return unless (1..7) === val
541
+ e.cwday = val
542
+ when 'V', 'OV'
543
+ return unless str.sub!(/\A(\d{1,2})/, '')
544
+ val = $1.to_i
545
+ return unless (1..53) === val
546
+ e.cweek = val
547
+ when 'v'
548
+ return unless _strptime_i(str, '%e-%b-%Y', e)
549
+ when 'w'
550
+ return unless str.sub!(/\A(\d{1})/, '')
551
+ val = $1.to_i
552
+ return unless (0..6) === val
553
+ e.wday = val
554
+ when 'X', 'EX'
555
+ return unless _strptime_i(str, '%H:%M:%S', e)
556
+ when 'x', 'Ex'
557
+ return unless _strptime_i(str, '%m/%d/%y', e)
558
+ when 'Y', 'EY'
559
+ return unless str.sub!(if num_pattern?($')
560
+ then /\A([-+]?\d{1,4})/
561
+ else /\A([-+]?\d{1,})/
562
+ end, '')
563
+ val = $1.to_i
564
+ e.year = val
565
+ when 'y', 'Ey', 'Oy'
566
+ return unless str.sub!(/\A(\d{1,2})/, '')
567
+ val = $1.to_i
568
+ return unless (0..99) === val
569
+ e.year = val
570
+ e._cent ||= if val >= 69 then 19 else 20 end
571
+ when 'Z', /\A:{0,3}z/
572
+ return unless str.sub!(/\A((?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
573
+ |[[:alpha:].\s]+(?:standard|daylight)\s+time\b
574
+ |[[:alpha:]]+(?:\s+dst)?\b
575
+ )/ix, '')
576
+ val = $1
577
+ e.zone = val
578
+ offset = zone_to_diff(val)
579
+ e.offset = offset
580
+ when '%'
581
+ return unless str.sub!(/\A%/, '')
582
+ when '+'
583
+ return unless _strptime_i(str, '%a %b %e %H:%M:%S %Z %Y', e)
584
+ else
585
+ return unless str.sub!(Regexp.new('\\A' + Regexp.quote(a)), '')
586
+ end
587
+ else
588
+ case c
589
+ when /\A[\s\v]/
590
+ str.sub!(/\A[\s\v]+/, '')
591
+ else
592
+ return unless str.sub!(Regexp.new('\\A' + Regexp.quote(a)), '')
593
+ end
594
+ end
595
+ end
596
+ end
597
+
598
+ private_class_method :_strptime_i
599
+
600
+ def self._strptime(str, fmt='%F')
601
+ str = str.dup
602
+ e = Format::Bag.new
603
+ return unless _strptime_i(str, fmt, e)
604
+
605
+ if e._cent
606
+ if e.cwyear
607
+ e.cwyear += e._cent * 100
608
+ end
609
+ if e.year
610
+ e. year += e._cent * 100
611
+ end
612
+ end
613
+
614
+ if e._merid
615
+ if e.hour
616
+ e.hour %= 12
617
+ e.hour += e._merid
618
+ end
619
+ end
620
+
621
+ unless str.empty?
622
+ e.leftover = str
623
+ end
624
+
625
+ e.to_hash
626
+ end
627
+
628
+ def self.s3e(e, y, m, d, bc=false)
629
+ unless String === m
630
+ m = m.to_s
631
+ end
632
+
633
+ if y && m && !d
634
+ y, m, d = d, y, m
635
+ end
636
+
637
+ if y == nil
638
+ if d && d.size > 2
639
+ y = d
640
+ d = nil
641
+ end
642
+ if d && d[0,1] == "'"
643
+ y = d
644
+ d = nil
645
+ end
646
+ end
647
+
648
+ if y
649
+ y.scan(/(\d+)(.+)?/)
650
+ if $2
651
+ y, d = d, $1
652
+ end
653
+ end
654
+
655
+ if m
656
+ if m[0,1] == "'" || m.size > 2
657
+ y, m, d = m, d, y # us -> be
658
+ end
659
+ end
660
+
661
+ if d
662
+ if d[0,1] == "'" || d.size > 2
663
+ y, d = d, y
664
+ end
665
+ end
666
+
667
+ if y
668
+ y =~ /([-+])?(\d+)/
669
+ if $1 || $2.size > 2
670
+ c = false
671
+ end
672
+ iy = $&.to_i
673
+ if bc
674
+ iy = -iy + 1
675
+ end
676
+ e.year = iy
677
+ end
678
+
679
+ if m
680
+ m =~ /\d+/
681
+ e.mon = $&.to_i
682
+ end
683
+
684
+ if d
685
+ d =~ /\d+/
686
+ e.mday = $&.to_i
687
+ end
688
+
689
+ if c != nil
690
+ e._comp = c
691
+ end
692
+
693
+ end
694
+
695
+ private_class_method :s3e
696
+
697
+ def self._parse_day(str, e) # :nodoc:
698
+ if str.sub!(/\b(#{Format::ABBR_DAYS.keys.join('|')})[^-\d\s]*/ino, ' ')
699
+ e.wday = Format::ABBR_DAYS[$1.downcase]
700
+ true
701
+ =begin
702
+ elsif str.sub!(/\b(?!\dth)(su|mo|tu|we|th|fr|sa)\b/in, ' ')
703
+ e.wday = %w(su mo tu we th fr sa).index($1.downcase)
704
+ true
705
+ =end
706
+ end
707
+ end
708
+
709
+ def self._parse_time(str, e) # :nodoc:
710
+ if str.sub!(
711
+ /(
712
+ (?:
713
+ \d+\s*:\s*\d+
714
+ (?:
715
+ \s*:\s*\d+(?:[,.]\d*)?
716
+ )?
717
+ |
718
+ \d+\s*h(?:\s*\d+m?(?:\s*\d+s?)?)?
719
+ )
720
+ (?:
721
+ \s*
722
+ [ap](?:m\b|\.m\.)
723
+ )?
724
+ |
725
+ \d+\s*[ap](?:m\b|\.m\.)
726
+ )
727
+ (?:
728
+ \s*
729
+ (
730
+ (?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
731
+ |
732
+ [[:alpha:].\s]+(?:standard|daylight)\stime\b
733
+ |
734
+ [[:alpha:]]+(?:\sdst)?\b
735
+ )
736
+ )?
737
+ /inx,
738
+ ' ')
739
+
740
+ t = $1
741
+ e.zone = $2 if $2
742
+
743
+ t =~ /\A(\d+)h?
744
+ (?:\s*:?\s*(\d+)m?
745
+ (?:
746
+ \s*:?\s*(\d+)(?:[,.](\d+))?s?
747
+ )?
748
+ )?
749
+ (?:\s*([ap])(?:m\b|\.m\.))?/inx
750
+
751
+ e.hour = $1.to_i
752
+ e.min = $2.to_i if $2
753
+ e.sec = $3.to_i if $3
754
+ e.sec_fraction = Rational($4.to_i, 10**$4.size) if $4
755
+
756
+ if $5
757
+ e.hour %= 12
758
+ if $5.downcase == 'p'
759
+ e.hour += 12
760
+ end
761
+ end
762
+ true
763
+ end
764
+ end
765
+
766
+ =begin
767
+ def self._parse_beat(str, e) # :nodoc:
768
+ if str.sub!(/@\s*(\d+)(?:[,.](\d*))?/, ' ')
769
+ beat = Rational($1.to_i)
770
+ beat += Rational($2.to_i, 10**$2.size) if $2
771
+ secs = Rational(beat, 1000)
772
+ h, min, s, fr = self.day_fraction_to_time(secs)
773
+ e.hour = h
774
+ e.min = min
775
+ e.sec = s
776
+ e.sec_fraction = fr * 86400
777
+ e.zone = '+01:00'
778
+ true
779
+ end
780
+ end
781
+ =end
782
+
783
+ def self._parse_eu(str, e) # :nodoc:
784
+ if str.sub!(
785
+ /'?(\d+)[^-\d\s]*
786
+ \s*
787
+ (#{Format::ABBR_MONTHS.keys.join('|')})[^-\d\s']*
788
+ (?:
789
+ \s*
790
+ (c(?:e|\.e\.)|b(?:ce|\.c\.e\.)|a(?:d|\.d\.)|b(?:c|\.c\.))?
791
+ \s*
792
+ ('?-?\d+(?:(?:st|nd|rd|th)\b)?)
793
+ )?
794
+ /inox,
795
+ ' ') # '
796
+ s3e(e, $4, Format::ABBR_MONTHS[$2.downcase], $1,
797
+ $3 && $3[0,1].downcase == 'b')
798
+ true
799
+ end
800
+ end
801
+
802
+ def self._parse_us(str, e) # :nodoc:
803
+ if str.sub!(
804
+ /\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-\d\s']*
805
+ \s*
806
+ ('?\d+)[^-\d\s']*
807
+ (?:
808
+ \s*
809
+ (c(?:e|\.e\.)|b(?:ce|\.c\.e\.)|a(?:d|\.d\.)|b(?:c|\.c\.))?
810
+ \s*
811
+ ('?-?\d+)
812
+ )?
813
+ /inox,
814
+ ' ') # '
815
+ s3e(e, $4, Format::ABBR_MONTHS[$1.downcase], $2,
816
+ $3 && $3[0,1].downcase == 'b')
817
+ true
818
+ end
819
+ end
820
+
821
+ def self._parse_iso(str, e) # :nodoc:
822
+ if str.sub!(/('?[-+]?\d+)-(\d+)-('?-?\d+)/n, ' ')
823
+ s3e(e, $1, $2, $3)
824
+ true
825
+ end
826
+ end
827
+
828
+ def self._parse_iso2(str, e) # :nodoc:
829
+ if str.sub!(/\b(\d{2}|\d{4})?-?w(\d{2})(?:-?(\d))?\b/in, ' ')
830
+ e.cwyear = $1.to_i if $1
831
+ e.cweek = $2.to_i
832
+ e.cwday = $3.to_i if $3
833
+ true
834
+ elsif str.sub!(/-w-(\d)\b/in, ' ')
835
+ e.cwday = $1.to_i
836
+ true
837
+ elsif str.sub!(/--(\d{2})?-(\d{2})\b/n, ' ')
838
+ e.mon = $1.to_i if $1
839
+ e.mday = $2.to_i
840
+ true
841
+ elsif str.sub!(/--(\d{2})(\d{2})?\b/n, ' ')
842
+ e.mon = $1.to_i
843
+ e.mday = $2.to_i if $2
844
+ true
845
+ elsif /[,.](\d{2}|\d{4})-\d{3}\b/n !~ str &&
846
+ str.sub!(/\b(\d{2}|\d{4})-(\d{3})\b/n, ' ')
847
+ e.year = $1.to_i
848
+ e.yday = $2.to_i
849
+ true
850
+ elsif /\d-\d{3}\b/n !~ str &&
851
+ str.sub!(/\b-(\d{3})\b/n, ' ')
852
+ e.yday = $1.to_i
853
+ true
854
+ end
855
+ end
856
+
857
+ def self._parse_jis(str, e) # :nodoc:
858
+ if str.sub!(/\b([mtsh])(\d+)\.(\d+)\.(\d+)/in, ' ')
859
+ era = { 'm'=>1867,
860
+ 't'=>1911,
861
+ 's'=>1925,
862
+ 'h'=>1988
863
+ }[$1.downcase]
864
+ e.year = $2.to_i + era
865
+ e.mon = $3.to_i
866
+ e.mday = $4.to_i
867
+ true
868
+ end
869
+ end
870
+
871
+ def self._parse_vms(str, e) # :nodoc:
872
+ if str.sub!(/('?-?\d+)-(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
873
+ -('?-?\d+)/inox, ' ')
874
+ s3e(e, $3, Format::ABBR_MONTHS[$2.downcase], $1)
875
+ true
876
+ elsif str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
877
+ -('?-?\d+)(?:-('?-?\d+))?/inox, ' ')
878
+ s3e(e, $3, Format::ABBR_MONTHS[$1.downcase], $2)
879
+ true
880
+ end
881
+ end
882
+
883
+ def self._parse_sla(str, e) # :nodoc:
884
+ if str.sub!(%r|('?-?\d+)/\s*('?\d+)(?:\D\s*('?-?\d+))?|n, ' ') # '
885
+ s3e(e, $1, $2, $3)
886
+ true
887
+ end
888
+ end
889
+
890
+ def self._parse_dot(str, e) # :nodoc:
891
+ if str.sub!(%r|('?-?\d+)\.\s*('?\d+)\.\s*('?-?\d+)|n, ' ') # '
892
+ s3e(e, $1, $2, $3)
893
+ true
894
+ end
895
+ end
896
+
897
+ def self._parse_year(str, e) # :nodoc:
898
+ if str.sub!(/'(\d+)\b/n, ' ')
899
+ e.year = $1.to_i
900
+ true
901
+ end
902
+ end
903
+
904
+ def self._parse_mon(str, e) # :nodoc:
905
+ if str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})\S*/ino, ' ')
906
+ e.mon = Format::ABBR_MONTHS[$1.downcase]
907
+ true
908
+ end
909
+ end
910
+
911
+ def self._parse_mday(str, e) # :nodoc:
912
+ if str.sub!(/(\d+)(st|nd|rd|th)\b/in, ' ')
913
+ e.mday = $1.to_i
914
+ true
915
+ end
916
+ end
917
+
918
+ def self._parse_ddd(str, e) # :nodoc:
919
+ if str.sub!(
920
+ /([-+]?)(\d{2,14})
921
+ (?:
922
+ \s*
923
+ t?
924
+ \s*
925
+ (\d{2,6})?(?:[,.](\d*))?
926
+ )?
927
+ (?:
928
+ \s*
929
+ (
930
+ z\b
931
+ |
932
+ [-+]\d{1,4}\b
933
+ |
934
+ \[[-+]?\d[^\]]*\]
935
+ )
936
+ )?
937
+ /inx,
938
+ ' ')
939
+ case $2.size
940
+ when 2
941
+ if $3.nil? && $4
942
+ e.sec = $2[-2, 2].to_i
943
+ else
944
+ e.mday = $2[ 0, 2].to_i
945
+ end
946
+ when 4
947
+ if $3.nil? && $4
948
+ e.sec = $2[-2, 2].to_i
949
+ e.min = $2[-4, 2].to_i
950
+ else
951
+ e.mon = $2[ 0, 2].to_i
952
+ e.mday = $2[ 2, 2].to_i
953
+ end
954
+ when 6
955
+ if $3.nil? && $4
956
+ e.sec = $2[-2, 2].to_i
957
+ e.min = $2[-4, 2].to_i
958
+ e.hour = $2[-6, 2].to_i
959
+ else
960
+ e.year = ($1 + $2[ 0, 2]).to_i
961
+ e.mon = $2[ 2, 2].to_i
962
+ e.mday = $2[ 4, 2].to_i
963
+ end
964
+ when 8, 10, 12, 14
965
+ if $3.nil? && $4
966
+ e.sec = $2[-2, 2].to_i
967
+ e.min = $2[-4, 2].to_i
968
+ e.hour = $2[-6, 2].to_i
969
+ e.mday = $2[-8, 2].to_i
970
+ if $2.size >= 10
971
+ e.mon = $2[-10, 2].to_i
972
+ end
973
+ if $2.size == 12
974
+ e.year = ($1 + $2[-12, 2]).to_i
975
+ end
976
+ if $2.size == 14
977
+ e.year = ($1 + $2[-14, 4]).to_i
978
+ e._comp = false
979
+ end
980
+ else
981
+ e.year = ($1 + $2[ 0, 4]).to_i
982
+ e.mon = $2[ 4, 2].to_i
983
+ e.mday = $2[ 6, 2].to_i
984
+ e.hour = $2[ 8, 2].to_i if $2.size >= 10
985
+ e.min = $2[10, 2].to_i if $2.size >= 12
986
+ e.sec = $2[12, 2].to_i if $2.size >= 14
987
+ e._comp = false
988
+ end
989
+ when 3
990
+ if $3.nil? && $4
991
+ e.sec = $2[-2, 2].to_i
992
+ e.min = $2[-3, 1].to_i
993
+ else
994
+ e.yday = $2[ 0, 3].to_i
995
+ end
996
+ when 5
997
+ if $3.nil? && $4
998
+ e.sec = $2[-2, 2].to_i
999
+ e.min = $2[-4, 2].to_i
1000
+ e.hour = $2[-5, 1].to_i
1001
+ else
1002
+ e.year = ($1 + $2[ 0, 2]).to_i
1003
+ e.yday = $2[ 2, 3].to_i
1004
+ end
1005
+ when 7
1006
+ if $3.nil? && $4
1007
+ e.sec = $2[-2, 2].to_i
1008
+ e.min = $2[-4, 2].to_i
1009
+ e.hour = $2[-6, 2].to_i
1010
+ e.mday = $2[-7, 1].to_i
1011
+ else
1012
+ e.year = ($1 + $2[ 0, 4]).to_i
1013
+ e.yday = $2[ 4, 3].to_i
1014
+ end
1015
+ end
1016
+ if $3
1017
+ if $4
1018
+ case $3.size
1019
+ when 2, 4, 6
1020
+ e.sec = $3[-2, 2].to_i
1021
+ e.min = $3[-4, 2].to_i if $3.size >= 4
1022
+ e.hour = $3[-6, 2].to_i if $3.size >= 6
1023
+ end
1024
+ else
1025
+ case $3.size
1026
+ when 2, 4, 6
1027
+ e.hour = $3[ 0, 2].to_i
1028
+ e.min = $3[ 2, 2].to_i if $3.size >= 4
1029
+ e.sec = $3[ 4, 2].to_i if $3.size >= 6
1030
+ end
1031
+ end
1032
+ end
1033
+ if $4
1034
+ e.sec_fraction = Rational($4.to_i, 10**$4.size)
1035
+ end
1036
+ if $5
1037
+ e.zone = $5
1038
+ if e.zone[0,1] == '['
1039
+ o, n, = e.zone[1..-2].split(':')
1040
+ e.zone = n || o
1041
+ if /\A\d/ =~ o
1042
+ o = format('+%s', o)
1043
+ end
1044
+ e.offset = zone_to_diff(o)
1045
+ end
1046
+ end
1047
+ true
1048
+ end
1049
+ end
1050
+
1051
+ private_class_method :_parse_day, :_parse_time, # :_parse_beat,
1052
+ :_parse_eu, :_parse_us, :_parse_iso, :_parse_iso2,
1053
+ :_parse_jis, :_parse_vms, :_parse_sla, :_parse_dot,
1054
+ :_parse_year, :_parse_mon, :_parse_mday, :_parse_ddd
1055
+
1056
+ def self._parse(str, comp=true)
1057
+ str = str.dup
1058
+
1059
+ e = Date::Format::Bag.new
1060
+
1061
+ e._comp = comp
1062
+
1063
+ str.gsub!(/[^-+',.\/:@[:alnum:]\[\]\x80-\xff]+/n, ' ')
1064
+
1065
+ _parse_time(str, e) # || _parse_beat(str, e)
1066
+ _parse_day(str, e)
1067
+
1068
+ _parse_eu(str, e) ||
1069
+ _parse_us(str, e) ||
1070
+ _parse_iso(str, e) ||
1071
+ _parse_jis(str, e) ||
1072
+ _parse_vms(str, e) ||
1073
+ _parse_sla(str, e) ||
1074
+ _parse_dot(str, e) ||
1075
+ _parse_iso2(str, e) ||
1076
+ _parse_year(str, e) ||
1077
+ _parse_mon(str, e) ||
1078
+ _parse_mday(str, e) ||
1079
+ _parse_ddd(str, e)
1080
+
1081
+ if str.sub!(/\b(bc\b|bce\b|b\.c\.|b\.c\.e\.)/in, ' ')
1082
+ if e.year
1083
+ e.year = -e.year + 1
1084
+ end
1085
+ end
1086
+
1087
+ if str.sub!(/\A\s*(\d{1,2})\s*\z/n, ' ')
1088
+ if e.hour && !e.mday
1089
+ v = $1.to_i
1090
+ if (1..31) === v
1091
+ e.mday = v
1092
+ end
1093
+ end
1094
+ if e.mday && !e.hour
1095
+ v = $1.to_i
1096
+ if (0..24) === v
1097
+ e.hour = v
1098
+ end
1099
+ end
1100
+ end
1101
+
1102
+ if e._comp
1103
+ if e.cwyear
1104
+ if e.cwyear >= 0 && e.cwyear <= 99
1105
+ e.cwyear += if e.cwyear >= 69
1106
+ then 1900 else 2000 end
1107
+ end
1108
+ end
1109
+ if e.year
1110
+ if e.year >= 0 && e.year <= 99
1111
+ e.year += if e.year >= 69
1112
+ then 1900 else 2000 end
1113
+ end
1114
+ end
1115
+ end
1116
+
1117
+ e.offset ||= zone_to_diff(e.zone) if e.zone
1118
+
1119
+ e.to_hash
1120
+ end
1121
+
1122
+ def self._iso8601(str) # :nodoc:
1123
+ if /\A\s*(([-+]?\d{2,}|-)-\d{2}-\d{2}|
1124
+ ([-+]?\d{2,})?-\d{3}|
1125
+ (\d{2}|\d{4})?-w\d{2}-\d|
1126
+ -w-\d)
1127
+ (t
1128
+ \d{2}:\d{2}(:\d{2}([,.]\d+)?)?
1129
+ (z|[-+]\d{2}(:?\d{2})?)?)?\s*\z/inx =~ str
1130
+ _parse(str)
1131
+ elsif /\A\s*(([-+]?(\d{2}|\d{4})|--)\d{2}\d{2}|
1132
+ ([-+]?(\d{2}|\d{4}))?\d{3}|-\d{3}|
1133
+ (\d{2}|\d{4})?w\d{2}\d)
1134
+ (t?
1135
+ \d{2}\d{2}(\d{2}([,.]\d+)?)?
1136
+ (z|[-+]\d{2}(\d{2})?)?)?\s*\z/inx =~ str
1137
+ _parse(str)
1138
+ elsif /\A\s*(\d{2}:\d{2}(:\d{2}([,.]\d+)?)?
1139
+ (z|[-+]\d{2}(:?\d{2})?)?)?\s*\z/inx =~ str
1140
+ _parse(str)
1141
+ elsif /\A\s*(\d{2}\d{2}(\d{2}([,.]\d+)?)?
1142
+ (z|[-+]\d{2}(\d{2})?)?)?\s*\z/inx =~ str
1143
+ _parse(str)
1144
+ end
1145
+ end
1146
+
1147
+ def self._rfc3339(str) # :nodoc:
1148
+ if /\A\s*-?\d{4}-\d{2}-\d{2} # allow minus, anyway
1149
+ (t|\s)
1150
+ \d{2}:\d{2}:\d{2}(\.\d+)?
1151
+ (z|[-+]\d{2}:\d{2})\s*\z/inx =~ str
1152
+ _parse(str)
1153
+ end
1154
+ end
1155
+
1156
+ def self._xmlschema(str) # :nodoc:
1157
+ if /\A\s*(-?\d{4,})(?:-(\d{2})(?:-(\d{2}))?)?
1158
+ (?:t
1159
+ (\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?)?
1160
+ (z|[-+]\d{2}:\d{2})?\s*\z/inx =~ str
1161
+ e = Format::Bag.new
1162
+ e.year = $1.to_i
1163
+ e.mon = $2.to_i if $2
1164
+ e.mday = $3.to_i if $3
1165
+ e.hour = $4.to_i if $4
1166
+ e.min = $5.to_i if $5
1167
+ e.sec = $6.to_i if $6
1168
+ e.sec_fraction = Rational($7.to_i, 10**$7.size) if $7
1169
+ if $8
1170
+ e.zone = $8
1171
+ e.offset = zone_to_diff($8)
1172
+ end
1173
+ e.to_hash
1174
+ elsif /\A\s*(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?
1175
+ (z|[-+]\d{2}:\d{2})?\s*\z/inx =~ str
1176
+ e = Format::Bag.new
1177
+ e.hour = $1.to_i if $1
1178
+ e.min = $2.to_i if $2
1179
+ e.sec = $3.to_i if $3
1180
+ e.sec_fraction = Rational($4.to_i, 10**$4.size) if $4
1181
+ if $5
1182
+ e.zone = $5
1183
+ e.offset = zone_to_diff($5)
1184
+ end
1185
+ e.to_hash
1186
+ elsif /\A\s*(?:--(\d{2})(?:-(\d{2}))?|---(\d{2}))
1187
+ (z|[-+]\d{2}:\d{2})?\s*\z/inx =~ str
1188
+ e = Format::Bag.new
1189
+ e.mon = $1.to_i if $1
1190
+ e.mday = $2.to_i if $2
1191
+ e.mday = $3.to_i if $3
1192
+ if $4
1193
+ e.zone = $4
1194
+ e.offset = zone_to_diff($4)
1195
+ end
1196
+ e.to_hash
1197
+ end
1198
+ end
1199
+
1200
+ def self._rfc2822(str) # :nodoc:
1201
+ if /\A\s*(?:(?:#{Format::ABBR_DAYS.keys.join('|')})\s*,\s+)?
1202
+ \d{1,2}\s+
1203
+ (?:#{Format::ABBR_MONTHS.keys.join('|')})\s+
1204
+ -?(\d{2,})\s+ # allow minus, anyway
1205
+ \d{2}:\d{2}(:\d{2})?\s*
1206
+ (?:[-+]\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\s*\z/inox =~ str
1207
+ e = _parse(str, false)
1208
+ if $1.size < 4
1209
+ if e[:year] < 50
1210
+ e[:year] += 2000
1211
+ elsif e[:year] < 1000
1212
+ e[:year] += 1900
1213
+ end
1214
+ end
1215
+ e
1216
+ end
1217
+ end
1218
+
1219
+ class << self; alias_method :_rfc822, :_rfc2822 end
1220
+
1221
+ def self._httpdate(str) # :nodoc:
1222
+ if /\A\s*(#{Format::ABBR_DAYS.keys.join('|')})\s*,\s+
1223
+ \d{2}\s+
1224
+ (#{Format::ABBR_MONTHS.keys.join('|')})\s+
1225
+ -?\d{4}\s+ # allow minus, anyway
1226
+ \d{2}:\d{2}:\d{2}\s+
1227
+ gmt\s*\z/inox =~ str
1228
+ _rfc2822(str)
1229
+ elsif /\A\s*(#{Format::DAYS.keys.join('|')})\s*,\s+
1230
+ \d{2}\s*-\s*
1231
+ (#{Format::ABBR_MONTHS.keys.join('|')})\s*-\s*
1232
+ \d{2}\s+
1233
+ \d{2}:\d{2}:\d{2}\s+
1234
+ gmt\s*\z/inox =~ str
1235
+ _parse(str)
1236
+ elsif /\A\s*(#{Format::ABBR_DAYS.keys.join('|')})\s+
1237
+ (#{Format::ABBR_MONTHS.keys.join('|')})\s+
1238
+ \d{1,2}\s+
1239
+ \d{2}:\d{2}:\d{2}\s+
1240
+ \d{4}\s*\z/inox =~ str
1241
+ _parse(str)
1242
+ end
1243
+ end
1244
+
1245
+ def self._jisx0301(str) # :nodoc:
1246
+ if /\A\s*[mtsh]?\d{2}\.\d{2}\.\d{2}
1247
+ (t
1248
+ (\d{2}:\d{2}(:\d{2}([,.]\d*)?)?
1249
+ (z|[-+]\d{2}(:?\d{2})?)?)?)?\s*\z/inx =~ str
1250
+ if /\A\s*\d/ =~ str
1251
+ _parse(str.sub(/\A\s*(\d)/, 'h\1'))
1252
+ else
1253
+ _parse(str)
1254
+ end
1255
+ else
1256
+ _iso8601(str)
1257
+ end
1258
+ end
1259
+
1260
+ t = Module.new do
1261
+
1262
+ private
1263
+
1264
+ def zone_to_diff(zone) # :nodoc:
1265
+ zone = zone.downcase
1266
+ if zone.sub!(/\s+(standard|daylight)\s+time\z/, '')
1267
+ dst = $1 == 'daylight'
1268
+ else
1269
+ dst = zone.sub!(/\s+dst\z/, '')
1270
+ end
1271
+ if Date::Format::ZONES.include?(zone)
1272
+ offset = Date::Format::ZONES[zone]
1273
+ offset += 3600 if dst
1274
+ elsif zone.sub!(/\A(?:gmt|utc?)?([-+])/, '')
1275
+ sign = $1
1276
+ if zone.include?(':')
1277
+ hour, min, sec, = zone.split(':')
1278
+ elsif zone.include?(',') || zone.include?('.')
1279
+ hour, fr, = zone.split(/[,.]/)
1280
+ min = Rational(fr.to_i, 10**fr.size) * 60
1281
+ else
1282
+ case zone.size
1283
+ when 3
1284
+ hour = zone[0,1]
1285
+ min = zone[1,2]
1286
+ else
1287
+ hour = zone[0,2]
1288
+ min = zone[2,2]
1289
+ sec = zone[4,2]
1290
+ end
1291
+ end
1292
+ offset = hour.to_i * 3600 + min.to_i * 60 + sec.to_i
1293
+ offset *= -1 if sign == '-'
1294
+ end
1295
+ offset
1296
+ end
1297
+
1298
+ end
1299
+
1300
+ extend t
1301
+ include t
1302
+
1303
+ end
1304
+
1305
+ class DateTime < Date
1306
+
1307
+ def strftime(fmt='%FT%T%:z')
1308
+ super(fmt)
1309
+ end
1310
+
1311
+ def self._strptime(str, fmt='%FT%T%z')
1312
+ super(str, fmt)
1313
+ end
1314
+
1315
+ def iso8601_timediv(n) # :nodoc:
1316
+ strftime('T%T' +
1317
+ if n < 1
1318
+ ''
1319
+ else
1320
+ '.%0*d' % [n, (sec_fraction / Rational(1, 10**n)).round]
1321
+ end +
1322
+ '%:z')
1323
+ end
1324
+
1325
+ private :iso8601_timediv
1326
+
1327
+ def iso8601(n=0)
1328
+ super() + iso8601_timediv(n)
1329
+ end
1330
+
1331
+ def rfc3339(n=0) iso8601(n) end
1332
+
1333
+ def xmlschema(n=0) iso8601(n) end # :nodoc:
1334
+
1335
+ def jisx0301(n=0)
1336
+ super() + iso8601_timediv(n)
1337
+ end
1338
+
1339
+ end