Project

General

Profile

Feature #4452 ยป date_format.patch

jeremyevans0 (Jeremy Evans), 03/01/2011 10:46 AM

View differences:

lib/date/format.rb
[MONTHS, DAYS, ABBR_MONTHS, ABBR_DAYS, ZONES].each do |x|
x.freeze
end
class BagStruct < Struct # :nodoc:
def to_hash
h = {}
members.each do |k|
unless /\A_/ =~ k.to_s || self[k].nil?
h[k] = self[k]
end
end
h
end
end
Bag = BagStruct.new(:year, :mon, :yday, :mday, :wday,
:cwyear, :cweek, :cwday,
:hour, :min, :sec, :sec_fraction,
:wnum0, :wnum1, :seconds,
:zone, :offset, :leftover,
:_cent, :_merid, :_comp)
end
def emit(e, f) # :nodoc:
......
str.sub!(/\A(#{Format::ABBR_DAYS.keys.join('|')})/io, '')
val = Format::DAYS[$1.downcase] || Format::ABBR_DAYS[$1.downcase]
return unless val
e.wday = val
e[:wday] = val
when 'B', 'b', 'h'
return unless str.sub!(/\A(#{Format::MONTHS.keys.join('|')})/io, '') ||
str.sub!(/\A(#{Format::ABBR_MONTHS.keys.join('|')})/io, '')
val = Format::MONTHS[$1.downcase] || Format::ABBR_MONTHS[$1.downcase]
return unless val
e.mon = val
e[:mon] = val
when 'C', 'EC'
return unless str.sub!(if num_pattern?($')
then /\A([-+]?\d{1,2})/
else /\A([-+]?\d{1,})/
end, '')
val = $1.to_i
e._cent = val
e[:_][:cent] = val
when 'c', 'Ec'
return unless _strptime_i(str, '%a %b %e %H:%M:%S %Y', e)
when 'D'
......
return unless str.sub!(/\A( \d|\d{1,2})/, '')
val = $1.to_i
return unless (1..31) === val
e.mday = val
e[:mday] = val
when 'F'
return unless _strptime_i(str, '%Y-%m-%d', e)
when 'G'
......
else /\A([-+]?\d{1,})/
end, '')
val = $1.to_i
e.cwyear = val
e[:cwyear] = val
when 'g'
return unless str.sub!(/\A(\d{1,2})/, '')
val = $1.to_i
return unless (0..99) === val
e.cwyear = val
e._cent ||= if val >= 69 then 19 else 20 end
e[:cwyear] = val
e[:_][:cent] ||= if val >= 69 then 19 else 20 end
when 'H', 'k', 'OH'
return unless str.sub!(/\A( \d|\d{1,2})/, '')
val = $1.to_i
return unless (0..24) === val
e.hour = val
e[:hour] = val
when 'I', 'l', 'OI'
return unless str.sub!(/\A( \d|\d{1,2})/, '')
val = $1.to_i
return unless (1..12) === val
e.hour = val
e[:hour] = val
when 'j'
return unless str.sub!(/\A(\d{1,3})/, '')
val = $1.to_i
return unless (1..366) === val
e.yday = val
e[:yday] = val
when 'L'
return unless str.sub!(if num_pattern?($')
then /\A([-+]?\d{1,3})/
......
end, '')
# val = Rational($1.to_i, 10**3)
val = Rational($1.to_i, 10**$1.size)
e.sec_fraction = val
e[:sec_fraction] = val
when 'M', 'OM'
return unless str.sub!(/\A(\d{1,2})/, '')
val = $1.to_i
return unless (0..59) === val
e.min = val
e[:min] = val
when 'm', 'Om'
return unless str.sub!(/\A(\d{1,2})/, '')
val = $1.to_i
return unless (1..12) === val
e.mon = val
e[:mon] = val
when 'N'
return unless str.sub!(if num_pattern?($')
then /\A([-+]?\d{1,9})/
......
end, '')
# val = Rational($1.to_i, 10**9)
val = Rational($1.to_i, 10**$1.size)
e.sec_fraction = val
e[:sec_fraction] = val
when 'n', 't'
return unless _strptime_i(str, "\s", e)
when 'P', 'p'
return unless str.sub!(/\A([ap])(?:m\b|\.m\.)/i, '')
e._merid = if $1.downcase == 'a' then 0 else 12 end
e[:_][:merid] = if $1.downcase == 'a' then 0 else 12 end
when 'Q'
return unless str.sub!(/\A(-?\d{1,})/, '')
val = Rational($1.to_i, 10**3)
e.seconds = val
e[:seconds] = val
when 'R'
return unless _strptime_i(str, '%H:%M', e)
when 'r'
......
return unless str.sub!(/\A(\d{1,2})/, '')
val = $1.to_i
return unless (0..60) === val
e.sec = val
e[:sec] = val
when 's'
return unless str.sub!(/\A(-?\d{1,})/, '')
val = $1.to_i
e.seconds = val
e[:seconds] = val
when 'T'
return unless _strptime_i(str, '%H:%M:%S', e)
when 'U', 'W', 'OU', 'OW'
return unless str.sub!(/\A(\d{1,2})/, '')
val = $1.to_i
return unless (0..53) === val
e.__send__(if s[-1,1] == 'U' then :wnum0= else :wnum1= end, val)
e[s[-1,1] == 'U' ? :wnum0 : :wnum1] = val
when 'u', 'Ou'
return unless str.sub!(/\A(\d{1})/, '')
val = $1.to_i
return unless (1..7) === val
e.cwday = val
e[:cwday] = val
when 'V', 'OV'
return unless str.sub!(/\A(\d{1,2})/, '')
val = $1.to_i
return unless (1..53) === val
e.cweek = val
e[:cweek] = val
when 'v'
return unless _strptime_i(str, '%e-%b-%Y', e)
when 'w'
return unless str.sub!(/\A(\d{1})/, '')
val = $1.to_i
return unless (0..6) === val
e.wday = val
e[:wday] = val
when 'X', 'EX'
return unless _strptime_i(str, '%H:%M:%S', e)
when 'x', 'Ex'
......
else /\A([-+]?\d{1,})/
end, '')
val = $1.to_i
e.year = val
e[:year] = val
when 'y', 'Ey', 'Oy'
return unless str.sub!(/\A(\d{1,2})/, '')
val = $1.to_i
return unless (0..99) === val
e.year = val
e._cent ||= if val >= 69 then 19 else 20 end
e[:year] = val
e[:_][:cent] ||= if val >= 69 then 19 else 20 end
when 'Z', /\A:{0,3}z/
return unless str.sub!(/\A((?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
|[[:alpha:].\s]+(?:standard|daylight)\s+time\b
|[[:alpha:]]+(?:\s+dst)?\b
)/ix, '')
val = $1
e.zone = val
e[:zone] = val
offset = zone_to_diff(val)
e.offset = offset
e[:offset] = offset
when '%'
return unless str.sub!(/\A%/, '')
when '+'
......
def self._strptime(str, fmt='%F')
str = str.dup
e = Format::Bag.new
e = {:_ => {}}
return unless _strptime_i(str, fmt, e)
if e._cent
if e.cwyear
e.cwyear += e._cent * 100
if e[:_][:cent]
if e[:cwyear]
e[:cwyear] += e[:_][:cent] * 100
end
if e.year
e. year += e._cent * 100
if e[:year]
e[:year] += e[:_][:cent] * 100
end
end
if e._merid
if e.hour
e.hour %= 12
e.hour += e._merid
if e[:_][:merid]
if e[:hour]
e[:hour] %= 12
e[:hour] += e[:_][:merid]
end
end
unless str.empty?
e.leftover = str
e[:leftover] = str
end
e.to_hash
e.delete(:_)
e
end
def self.s3e(e, y, m, d, bc=false)
......
if bc
iy = -iy + 1
end
e.year = iy
e[:year] = iy
end
if m
m =~ /\d+/
e.mon = $&.to_i
e[:mon] = $&.to_i
end
if d
d =~ /\d+/
e.mday = $&.to_i
e[:mday] = $&.to_i
end
if c != nil
e._comp = c
e[:_][:comp] = c
end
end
......
def self._parse_day(str, e) # :nodoc:
if str.sub!(/\b(#{Format::ABBR_DAYS.keys.join('|')})[^-\d\s]*/io, ' ')
e.wday = Format::ABBR_DAYS[$1.downcase]
e[:wday] = Format::ABBR_DAYS[$1.downcase]
true
=begin
elsif str.sub!(/\b(?!\dth)(su|mo|tu|we|th|fr|sa)\b/i, ' ')
e.wday = %w(su mo tu we th fr sa).index($1.downcase)
e[:wday] = %w(su mo tu we th fr sa).index($1.downcase)
true
=end
end
......
' ')
t = $1
e.zone = $2 if $2
e[:zone] = $2 if $2
t =~ /\A(\d+)h?
(?:\s*:?\s*(\d+)m?
......
)?
(?:\s*([ap])(?:m\b|\.m\.))?/ix
e.hour = $1.to_i
e.min = $2.to_i if $2
e.sec = $3.to_i if $3
e.sec_fraction = Rational($4.to_i, 10**$4.size) if $4
e[:hour] = $1.to_i
e[:min] = $2.to_i if $2
e[:sec] = $3.to_i if $3
e[:sec_fraction] = Rational($4.to_i, 10**$4.size) if $4
if $5
e.hour %= 12
e[:hour] %= 12
if $5.downcase == 'p'
e.hour += 12
e[:hour] += 12
end
end
true
......
beat += Rational($2.to_i, 10**$2.size) if $2
secs = Rational(beat, 1000)
h, min, s, fr = self.day_fraction_to_time(secs)
e.hour = h
e.min = min
e.sec = s
e.sec_fraction = fr * 86400
e.zone = '+01:00'
e[:hour] = h
e[:min] = min
e[:sec] = s
e[:sec_fraction] = fr * 86400
e[:zone] = '+01:00'
true
end
end
......
def self._parse_iso2(str, e) # :nodoc:
if str.sub!(/\b(\d{2}|\d{4})?-?w(\d{2})(?:-?(\d))?\b/i, ' ')
e.cwyear = $1.to_i if $1
e.cweek = $2.to_i
e.cwday = $3.to_i if $3
e[:cwyear] = $1.to_i if $1
e[:cweek] = $2.to_i
e[:cwday] = $3.to_i if $3
true
elsif str.sub!(/-w-(\d)\b/i, ' ')
e.cwday = $1.to_i
e[:cwday] = $1.to_i
true
elsif str.sub!(/--(\d{2})?-(\d{2})\b/, ' ')
e.mon = $1.to_i if $1
e.mday = $2.to_i
e[:mon] = $1.to_i if $1
e[:mday] = $2.to_i
true
elsif str.sub!(/--(\d{2})(\d{2})?\b/, ' ')
e.mon = $1.to_i
e.mday = $2.to_i if $2
e[:mon] = $1.to_i
e[:mday] = $2.to_i if $2
true
elsif /[,.](\d{2}|\d{4})-\d{3}\b/ !~ str &&
str.sub!(/\b(\d{2}|\d{4})-(\d{3})\b/, ' ')
e.year = $1.to_i
e.yday = $2.to_i
e[:year] = $1.to_i
e[:yday] = $2.to_i
true
elsif /\d-\d{3}\b/ !~ str &&
str.sub!(/\b-(\d{3})\b/, ' ')
e.yday = $1.to_i
e[:yday] = $1.to_i
true
end
end
......
's'=>1925,
'h'=>1988
}[$1.downcase]
e.year = $2.to_i + era
e.mon = $3.to_i
e.mday = $4.to_i
e[:year] = $2.to_i + era
e[:mon] = $3.to_i
e[:mday] = $4.to_i
true
end
end
......
def self._parse_year(str, e) # :nodoc:
if str.sub!(/'(\d+)\b/, ' ')
e.year = $1.to_i
e[:year] = $1.to_i
true
end
end
def self._parse_mon(str, e) # :nodoc:
if str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})\S*/io, ' ')
e.mon = Format::ABBR_MONTHS[$1.downcase]
e[:mon] = Format::ABBR_MONTHS[$1.downcase]
true
end
end
def self._parse_mday(str, e) # :nodoc:
if str.sub!(/(\d+)(st|nd|rd|th)\b/i, ' ')
e.mday = $1.to_i
e[:mday] = $1.to_i
true
end
end
......
case $2.size
when 2
if $3.nil? && $4
e.sec = $2[-2, 2].to_i
e[:sec] = $2[-2, 2].to_i
else
e.mday = $2[ 0, 2].to_i
e[:mday] = $2[ 0, 2].to_i
end
when 4
if $3.nil? && $4
e.sec = $2[-2, 2].to_i
e.min = $2[-4, 2].to_i
e[:sec] = $2[-2, 2].to_i
e[:min] = $2[-4, 2].to_i
else
e.mon = $2[ 0, 2].to_i
e.mday = $2[ 2, 2].to_i
e[:mon] = $2[ 0, 2].to_i
e[:mday] = $2[ 2, 2].to_i
end
when 6
if $3.nil? && $4
e.sec = $2[-2, 2].to_i
e.min = $2[-4, 2].to_i
e.hour = $2[-6, 2].to_i
e[:sec] = $2[-2, 2].to_i
e[:min] = $2[-4, 2].to_i
e[:hour] = $2[-6, 2].to_i
else
e.year = ($1 + $2[ 0, 2]).to_i
e.mon = $2[ 2, 2].to_i
e.mday = $2[ 4, 2].to_i
e[:year] = ($1 + $2[ 0, 2]).to_i
e[:mon] = $2[ 2, 2].to_i
e[:mday] = $2[ 4, 2].to_i
end
when 8, 10, 12, 14
if $3.nil? && $4
e.sec = $2[-2, 2].to_i
e.min = $2[-4, 2].to_i
e.hour = $2[-6, 2].to_i
e.mday = $2[-8, 2].to_i
e[:sec] = $2[-2, 2].to_i
e[:min] = $2[-4, 2].to_i
e[:hour] = $2[-6, 2].to_i
e[:mday] = $2[-8, 2].to_i
if $2.size >= 10
e.mon = $2[-10, 2].to_i
e[:mon] = $2[-10, 2].to_i
end
if $2.size == 12
e.year = ($1 + $2[-12, 2]).to_i
e[:year] = ($1 + $2[-12, 2]).to_i
end
if $2.size == 14
e.year = ($1 + $2[-14, 4]).to_i
e._comp = false
e[:year] = ($1 + $2[-14, 4]).to_i
e[:_][:comp] = false
end
else
e.year = ($1 + $2[ 0, 4]).to_i
e.mon = $2[ 4, 2].to_i
e.mday = $2[ 6, 2].to_i
e.hour = $2[ 8, 2].to_i if $2.size >= 10
e.min = $2[10, 2].to_i if $2.size >= 12
e.sec = $2[12, 2].to_i if $2.size >= 14
e._comp = false
e[:year] = ($1 + $2[ 0, 4]).to_i
e[:mon] = $2[ 4, 2].to_i
e[:mday] = $2[ 6, 2].to_i
e[:hour] = $2[ 8, 2].to_i if $2.size >= 10
e[:min] = $2[10, 2].to_i if $2.size >= 12
e[:sec] = $2[12, 2].to_i if $2.size >= 14
e[:_][:comp] = false
end
when 3
if $3.nil? && $4
e.sec = $2[-2, 2].to_i
e.min = $2[-3, 1].to_i
e[:sec] = $2[-2, 2].to_i
e[:min] = $2[-3, 1].to_i
else
e.yday = $2[ 0, 3].to_i
e[:yday] = $2[ 0, 3].to_i
end
when 5
if $3.nil? && $4
e.sec = $2[-2, 2].to_i
e.min = $2[-4, 2].to_i
e.hour = $2[-5, 1].to_i
e[:sec] = $2[-2, 2].to_i
e[:min] = $2[-4, 2].to_i
e[:hour] = $2[-5, 1].to_i
else
e.year = ($1 + $2[ 0, 2]).to_i
e.yday = $2[ 2, 3].to_i
e[:year] = ($1 + $2[ 0, 2]).to_i
e[:yday] = $2[ 2, 3].to_i
end
when 7
if $3.nil? && $4
e.sec = $2[-2, 2].to_i
e.min = $2[-4, 2].to_i
e.hour = $2[-6, 2].to_i
e.mday = $2[-7, 1].to_i
e[:sec] = $2[-2, 2].to_i
e[:min] = $2[-4, 2].to_i
e[:hour] = $2[-6, 2].to_i
e[:mday] = $2[-7, 1].to_i
else
e.year = ($1 + $2[ 0, 4]).to_i
e.yday = $2[ 4, 3].to_i
e[:year] = ($1 + $2[ 0, 4]).to_i
e[:yday] = $2[ 4, 3].to_i
end
end
if $3
if $4
case $3.size
when 2, 4, 6
e.sec = $3[-2, 2].to_i
e.min = $3[-4, 2].to_i if $3.size >= 4
e.hour = $3[-6, 2].to_i if $3.size >= 6
e[:sec] = $3[-2, 2].to_i
e[:min] = $3[-4, 2].to_i if $3.size >= 4
e[:hour] = $3[-6, 2].to_i if $3.size >= 6
end
else
case $3.size
when 2, 4, 6
e.hour = $3[ 0, 2].to_i
e.min = $3[ 2, 2].to_i if $3.size >= 4
e.sec = $3[ 4, 2].to_i if $3.size >= 6
e[:hour] = $3[ 0, 2].to_i
e[:min] = $3[ 2, 2].to_i if $3.size >= 4
e[:sec] = $3[ 4, 2].to_i if $3.size >= 6
end
end
end
if $4
e.sec_fraction = Rational($4.to_i, 10**$4.size)
e[:sec_fraction] = Rational($4.to_i, 10**$4.size)
end
if $5
e.zone = $5
if e.zone[0,1] == '['
o, n, = e.zone[1..-2].split(':')
e.zone = n || o
e[:zone] = $5
if e[:zone][0,1] == '['
o, n, = e[:zone][1..-2].split(':')
e[:zone] = n || o
if /\A\d/ =~ o
o = format('+%s', o)
end
e.offset = zone_to_diff(o)
e[:offset] = zone_to_diff(o)
end
end
true
......
def self._parse(str, comp=true)
str = str.dup
e = Format::Bag.new
e._comp = comp
e = {:_ => {:comp => comp}}
str.gsub!(/[^-+',.\/:@[:alnum:]\[\]]+/, ' ')
_parse_time(str, e) # || _parse_beat(str, e)
......
_parse_ddd(str, e)
if str.sub!(/\b(bc\b|bce\b|b\.c\.|b\.c\.e\.)/i, ' ')
if e.year
e.year = -e.year + 1
if e[:year]
e[:year] = -e[:year] + 1
end
end
if str.sub!(/\A\s*(\d{1,2})\s*\z/, ' ')
if e.hour && !e.mday
if e[:hour] && !e[:mday]
v = $1.to_i
if (1..31) === v
e.mday = v
e[:mday] = v
end
end
if e.mday && !e.hour
if e[:mday] && !e[:hour]
v = $1.to_i
if (0..24) === v
e.hour = v
e[:hour] = v
end
end
end
if e._comp
if e.cwyear
if e.cwyear >= 0 && e.cwyear <= 99
e.cwyear += if e.cwyear >= 69
if e[:_][:comp]
if e[:cwyear]
if e[:cwyear] >= 0 && e[:cwyear] <= 99
e[:cwyear] += if e[:cwyear] >= 69
then 1900 else 2000 end
end
end
if e.year
if e.year >= 0 && e.year <= 99
e.year += if e.year >= 69
if e[:year]
if e[:year] >= 0 && e[:year] <= 99
e[:year] += if e[:year] >= 69
then 1900 else 2000 end
end
end
end
e.offset ||= zone_to_diff(e.zone) if e.zone
e[:offset] ||= zone_to_diff(e[:zone]) if e[:zone]
e.to_hash
e.delete(:_)
e
end
def self._iso8601(str) # :nodoc:
......
(?:t
(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?)?
(z|[-+]\d{2}:\d{2})?\s*\z/ix =~ str
e = Format::Bag.new
e.year = $1.to_i
e.mon = $2.to_i if $2
e.mday = $3.to_i if $3
e.hour = $4.to_i if $4
e.min = $5.to_i if $5
e.sec = $6.to_i if $6
e.sec_fraction = Rational($7.to_i, 10**$7.size) if $7
e = {}
e[:year] = $1.to_i
e[:mon] = $2.to_i if $2
e[:mday] = $3.to_i if $3
e[:hour] = $4.to_i if $4
e[:min] = $5.to_i if $5
e[:sec] = $6.to_i if $6
e[:sec_fraction] = Rational($7.to_i, 10**$7.size) if $7
if $8
e.zone = $8
e.offset = zone_to_diff($8)
e[:zone] = $8
e[:offset] = zone_to_diff($8)
end
e.to_hash
e
elsif /\A\s*(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?
(z|[-+]\d{2}:\d{2})?\s*\z/ix =~ str
e = Format::Bag.new
e.hour = $1.to_i if $1
e.min = $2.to_i if $2
e.sec = $3.to_i if $3
e.sec_fraction = Rational($4.to_i, 10**$4.size) if $4
e = {}
e[:hour] = $1.to_i if $1
e[:min] = $2.to_i if $2
e[:sec] = $3.to_i if $3
e[:sec_fraction] = Rational($4.to_i, 10**$4.size) if $4
if $5
e.zone = $5
e.offset = zone_to_diff($5)
e[:zone] = $5
e[:offset] = zone_to_diff($5)
end
e.to_hash
e
elsif /\A\s*(?:--(\d{2})(?:-(\d{2}))?|---(\d{2}))
(z|[-+]\d{2}:\d{2})?\s*\z/ix =~ str
e = Format::Bag.new
e.mon = $1.to_i if $1
e.mday = $2.to_i if $2
e.mday = $3.to_i if $3
e = {}
e[:mon] = $1.to_i if $1
e[:mday] = $2.to_i if $2
e[:mday] = $3.to_i if $3
if $4
e.zone = $4
e.offset = zone_to_diff($4)
e[:zone] = $4
e[:offset] = zone_to_diff($4)
end
e.to_hash
e
end
end
    (1-1/1)