Skip to content

Commit

Permalink
Add %G, %g, %V direcives to Time::Format
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Oct 2, 2018
1 parent c9cac1b commit cd4303c
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 6 deletions.
45 changes: 42 additions & 3 deletions spec/std/time/format_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,27 @@ describe Time::Format do
t3.to_s("%u").to_s.should eq("7")
t3.to_s("%w").to_s.should eq("0")

# TODO %G
# TODO %g
# TODO %V
Time.utc(1985, 4, 12).to_s("%G-W%V-%u").should eq "1985-W15-5"
Time.utc(2005, 1, 1).to_s("%G-W%V-%u").should eq "2004-W53-6"
Time.utc(2005, 1, 2).to_s("%G-W%V-%u").should eq "2004-W53-7"
Time.utc(2005, 12, 31).to_s("%G-W%V-%u").should eq "2005-W52-6"
Time.utc(2006, 1, 1).to_s("%G-W%V-%u").should eq "2005-W52-7"
Time.utc(2006, 1, 2).to_s("%G-W%V-%u").should eq "2006-W01-1"
Time.utc(2006, 12, 31).to_s("%G-W%V-%u").should eq "2006-W52-7"
Time.utc(2007, 1, 1).to_s("%G-W%V-%u").should eq "2007-W01-1"
Time.utc(2007, 12, 30).to_s("%G-W%V-%u").should eq "2007-W52-7"
Time.utc(2007, 12, 31).to_s("%G-W%V-%u").should eq "2008-W01-1"
Time.utc(2008, 1, 1).to_s("%G-W%V-%u").should eq "2008-W01-2"
Time.utc(2008, 12, 28).to_s("%G-W%V-%u").should eq "2008-W52-7"
Time.utc(2008, 12, 29).to_s("%G-W%V-%u").should eq "2009-W01-1"
Time.utc(2008, 12, 30).to_s("%G-W%V-%u").should eq "2009-W01-2"
Time.utc(2008, 12, 31).to_s("%G-W%V-%u").should eq "2009-W01-3"
Time.utc(2009, 1, 1).to_s("%G-W%V-%u").should eq "2009-W01-4"
Time.utc(2009, 12, 31).to_s("%G-W%V-%u").should eq "2009-W53-4"
Time.utc(2010, 1, 1).to_s("%G-W%V-%u").should eq "2009-W53-5"
Time.utc(2010, 1, 2).to_s("%G-W%V-%u").should eq "2009-W53-6"
Time.utc(2010, 1, 3).to_s("%G-W%V-%u").should eq "2009-W53-7"
Time.utc(1985, 4, 12).to_s("%g-W%V-%u").should eq "85-W15-5"
# TODO %U
# TODO %W
# TODO %s
Expand Down Expand Up @@ -208,6 +226,27 @@ describe Time::Format do
parse_time("今は Friday, October 31, 2014", "今は %A, %B %d, %Y").to_s.should eq("2014-10-31 00:00:00 UTC")
parse_time("epoch: 1459864667", "epoch: %s").epoch.should eq(1459864667)
parse_time("epoch: -1459864667", "epoch: %s").epoch.should eq(-1459864667)

parse_time("1985-W15-5", "%G-W%V-%u").should eq(Time.utc(1985, 4, 12))
parse_time("2004-W53-6", "%G-W%V-%u").should eq(Time.utc(2005, 1, 1))
parse_time("2004-W53-7", "%G-W%V-%u").should eq(Time.utc(2005, 1, 2))
parse_time("2005-W52-6", "%G-W%V-%u").should eq(Time.utc(2005, 12, 31))
parse_time("2005-W52-7", "%G-W%V-%u").should eq(Time.utc(2006, 1, 1))
parse_time("2006-W01-1", "%G-W%V-%u").should eq(Time.utc(2006, 1, 2))
parse_time("2006-W52-7", "%G-W%V-%u").should eq(Time.utc(2006, 12, 31))
parse_time("2007-W01-1", "%G-W%V-%u").should eq(Time.utc(2007, 1, 1))
parse_time("2007-W52-7", "%G-W%V-%u").should eq(Time.utc(2007, 12, 30))
parse_time("2008-W01-1", "%G-W%V-%u").should eq(Time.utc(2007, 12, 31))
parse_time("2008-W01-2", "%G-W%V-%u").should eq(Time.utc(2008, 1, 1))
parse_time("2008-W52-7", "%G-W%V-%u").should eq(Time.utc(2008, 12, 28))
parse_time("2009-W01-1", "%G-W%V-%u").should eq(Time.utc(2008, 12, 29))
parse_time("2009-W01-2", "%G-W%V-%u").should eq(Time.utc(2008, 12, 30))
parse_time("2009-W01-3", "%G-W%V-%u").should eq(Time.utc(2008, 12, 31))
parse_time("2009-W01-4", "%G-W%V-%u").should eq(Time.utc(2009, 1, 1))
parse_time("2009-W53-4", "%G-W%V-%u").should eq(Time.utc(2009, 12, 31))
parse_time("2009-W53-5", "%G-W%V-%u").should eq(Time.utc(2010, 1, 1))
parse_time("2009-W53-6", "%G-W%V-%u").should eq(Time.utc(2010, 1, 2))
parse_time("2009-W53-7", "%G-W%V-%u").should eq(Time.utc(2010, 1, 3))
end

it "parses timezone" do
Expand Down
3 changes: 3 additions & 0 deletions src/time/format.cr
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ require "./format/parser"
# * **%D**: date (04/05/16)
# * **%e**: day of month, blank padded (" 1", " 2", ..., "10", "11", ...)
# * **%F**: ISO 8601 date (2016-04-05)
# * **%g**: week-based calendar year modulo 100 (00..99)
# * **%G**: week-based calendar year (0001..9999)
# * **%h**: (same as %b) short month name (Jan, Feb, Mar, ...)
# * **%H**: hour of the day, 24-hour clock, zero padded (00, 01, ..., 24)
# * **%I**: hour of the day, 12-hour clock, zero padded (00, 01, ..., 12)
Expand All @@ -47,6 +49,7 @@ require "./format/parser"
# * **%S**: seconds, zero padded (00, 01, ..., 59)
# * **%T**: 24-hour time (13:04:05)
# * **%u**: day of week (Monday is 1, 1..7)
# * **%V**: ISO calendar week number of the week-based year (01..53)
# * **%w**: day of week (Sunday is 0, 0..6)
# * **%x**: (same as %D) date (04/05/16)
# * **%X**: (same as %T) 24-hour time (13:04:05)
Expand Down
12 changes: 12 additions & 0 deletions src/time/format/formatter.cr
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ struct Time::Format
year
end

def calendar_week_year
pad4(time.calendar_week[0], '0')
end

def calendar_week_year_modulo100
pad2(time.calendar_week[0] % 100, '0')
end

def month
io << time.month
end
Expand Down Expand Up @@ -55,6 +63,10 @@ struct Time::Format
io << get_short_month_name.upcase
end

def calendar_week_week
pad2(time.calendar_week[1], '0')
end

def day_of_month
io << time.day
end
Expand Down
27 changes: 24 additions & 3 deletions src/time/format/parser.cr
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ struct Time::Format

@epoch : Int64?
@location : Location?
@calendar_week_week : Int32?
@calendar_week_year : Int32?
@day_of_week : Time::DayOfWeek?

def initialize(string)
@reader = Char::Reader.new(string)
Expand All @@ -45,7 +48,13 @@ struct Time::Format
raise "Time format did not include time zone and no default location provided", pos: false
end

time = Time.new @year, @month, @day, @hour, @minute, @second, nanosecond: @nanosecond, location: location
if (calendar_week_week = @calendar_week_week) && (calendar_week_year = @calendar_week_year) && (day_of_week = @day_of_week)
# If all components of a week date are available, they are used to create a Time instance
time = Time.week_date calendar_week_year, calendar_week_week, day_of_week, @hour, @minute, @second, nanosecond: @nanosecond, location: location
else
time = Time.new @year, @month, @day, @hour, @minute, @second, nanosecond: @nanosecond, location: location
end

time = time.add_span 0, @nanosecond_offset

time
Expand Down Expand Up @@ -81,6 +90,14 @@ struct Time::Format
end
end

def calendar_week_year
@calendar_week_year = consume_number(4)
end

def calendar_week_year_modulo100
@calendar_week_year = consume_number(2)
end

def month
@month = consume_number(2)
end
Expand Down Expand Up @@ -131,6 +148,10 @@ struct Time::Format
month_name
end

def calendar_week_week
@calendar_week_week = consume_number(2)
end

def day_of_month
@day = consume_number(2)
end
Expand Down Expand Up @@ -261,11 +282,11 @@ struct Time::Format
end

def day_of_week_monday_1_7
consume_number(1)
@day_of_week = Time::DayOfWeek.from_value(consume_number(1))
end

def day_of_week_sunday_0_6
consume_number(1)
@day_of_week = Time::DayOfWeek.from_value(consume_number(1))
end

def epoch
Expand Down
6 changes: 6 additions & 0 deletions src/time/format/pattern.cr
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ struct Time::Format
day_of_month_blank_padded
when 'F'
year_month_day
when 'g'
calendar_week_year_modulo100
when 'G'
calendar_week_year
when 'H'
hour_24_zero_padded
when 'I'
Expand Down Expand Up @@ -68,6 +72,8 @@ struct Time::Format
twenty_four_hour_time_with_seconds
when 'u'
day_of_week_monday_1_7
when 'V'
calendar_week_week
when 'w'
day_of_week_sunday_0_6
when 'y'
Expand Down

0 comments on commit cd4303c

Please sign in to comment.