rhodes-framework 1.0.0

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.
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