stamp 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - ree
5
+ - rbx
6
+ - rbx-2.0
7
+ - jruby
8
+ - ruby-head
9
+ - 1.8.6
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stamp (0.0.2)
4
+ stamp (0.1.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -1,8 +1,10 @@
1
+ @stamp
1
2
  Feature: Stamping a date
2
3
  In order to format dates in a more programmer-friendly way
3
4
  the stamp method
4
5
  formats a date given a human-readable example.
5
6
 
7
+ @date
6
8
  Scenario Outline: Formatting dates by example
7
9
  Given the date October 9, 2011
8
10
  When I stamp the example "<example>"
@@ -33,15 +35,24 @@ Feature: Stamping a date
33
35
  | 1999-12-31 | 2011-10-09 |
34
36
  | DOB: 12-31-1999 | DOB: 10-09-2011 |
35
37
 
36
- @wip
37
- Scenario Outline: Examples that aren't supported quite yet
38
- Given the date October 9, 2011
38
+ @time
39
+ Scenario Outline: Formatting times by example
40
+ Given the time October 9, 2011 at 13:31:27
39
41
  When I stamp the example "<example>"
40
42
  Then I produce "<output>"
43
+ And I like turtles
41
44
 
42
45
  Examples:
43
- | example | output |
44
- | | |
46
+ | example | output |
47
+ | 8:59 am | 1:31 pm |
48
+ | 8:59am | 1:31pm |
49
+ | 08:59 AM | 01:31 PM |
50
+ | 08:59 PM | 01:31 PM |
51
+ | 23:59 | 13:31 |
52
+ | 8:59:59 am | 1:31:27 pm |
53
+ | 08:59:59 AM | 01:31:27 PM |
54
+ | 08:59:59 PM | 01:31:27 PM |
55
+ | 23:59:59 | 13:31:27 |
45
56
 
46
57
  Scenario: strftime directives just get passed through
47
58
  Given the date December 21, 2012
@@ -52,3 +63,16 @@ Feature: Stamping a date
52
63
  Given the date December 9, 2011
53
64
  When I stamp the example "Just some plain old text."
54
65
  Then I produce "Just some plain old text."
66
+
67
+
68
+ @wip
69
+ Scenario Outline: Examples that aren't supported yet
70
+ Given the date October 9, 2011
71
+ When I stamp the example "<example>"
72
+ Then I produce "<output>"
73
+
74
+ Examples:
75
+ | example | output |
76
+ | 8 am | 1 pm |
77
+ | 8am | 1pm |
78
+ | 8AM | 1PM |
@@ -1,13 +1,24 @@
1
+ module StampStepHelpers
2
+ def month(month_name)
3
+ month = Date::MONTHNAMES.index(month_name) || Date::ABBR_MONTHNAMES.index(month_name)
4
+ assert (1..12).include?(month), "Invalid month: #{month_name}"
5
+ return month
6
+ end
7
+ end
8
+ World(StampStepHelpers)
9
+
1
10
  Given /^the date (\w+) (\d+), (\d{4})$/ do |month_name, day, year|
2
- month = Date::MONTHNAMES.index(month_name) || Date::ABBR_MONTHNAMES.index(month_name)
3
- assert (1..12).include?(month), "Invalid month: #{month_name}"
4
- @date = Date.new(year.to_i, month, day.to_i)
11
+ @target = Date.new(year.to_i, month(month_name), day.to_i)
12
+ end
13
+
14
+ Given /^the time (\w+) (\d+), (\d+) at (\d{2}):(\d{2}):(\d{2})$/ do |month_name, day, year, hours, minutes, seconds|
15
+ @target = Time.new(year.to_i, month(month_name), day.to_i, hours.to_i, minutes.to_i, seconds.to_i)
5
16
  end
6
17
 
7
18
  When /^I stamp the example "([^"]*)"$/ do |example|
8
- @formatted_date = @date.stamp(example)
19
+ @stamped = @target.stamp(example)
9
20
  end
10
21
 
11
22
  Then /^I produce "([^"]*)"$/ do |expected|
12
- assert_equal expected, @formatted_date
23
+ assert_equal expected.strip, @stamped.strip
13
24
  end
data/lib/stamp.rb CHANGED
@@ -1,17 +1,14 @@
1
1
  require "stamp/version"
2
2
  require "date"
3
+ require "time"
3
4
 
4
5
  module Stamp
5
6
  def self.included(klass)
6
7
  klass.class_eval do
7
- # extend ClassMethods
8
8
  include InstanceMethods
9
9
  end
10
10
  end
11
11
 
12
- # module ClassMethods
13
- # end
14
-
15
12
  module InstanceMethods
16
13
 
17
14
  MONTHNAMES_REGEXP = /(#{Date::MONTHNAMES.compact.join('|')})/i
@@ -23,39 +20,98 @@ module Stamp
23
20
  TWO_DIGIT_REGEXP = /\d{2}/
24
21
  FOUR_DIGIT_REGEXP = /\d{4}/
25
22
 
26
- # DATE_DELIMITER_REGEXP = /(\/|\-)/ # forward slash or dash
23
+ TIME_REGEXP = /(\d{1,2})(:)(\d{2})(\s*)(:)?(\d{2})?(\s*)?([ap]m)?/i
27
24
 
28
- # OBVIOUS_MINUTES = 32..59
29
- # OBVIOUS_HOURS
30
- # OBVIOUS_SECONDS
25
+ MERIDIAN_LOWER_REGEXP = /(a|p)m/
26
+ MERIDIAN_UPPER_REGEXP = /(A|P)M/
31
27
 
28
+ # Disambiguate based on value
32
29
  OBVIOUS_YEARS = 60..99
33
30
  OBVIOUS_MONTHS = 12
34
31
  OBVIOUS_DAYS = 28..31
32
+ OBVIOUS_24_HOUR = 13..23
33
+
34
+ TWO_DIGIT_DATE_SUCCESSION = {
35
+ '%m' => '%d',
36
+ '%b' => '%d',
37
+ '%B' => '%d',
38
+ '%d' => '%y',
39
+ '%e' => '%y'
40
+ }
41
+
42
+ TWO_DIGIT_TIME_SUCCESSION = {
43
+ '%H' => '%M',
44
+ '%I' => '%M',
45
+ '%l' => '%M',
46
+ '%M' => '%S'
47
+ }
48
+
35
49
 
36
50
  def stamp(example)
37
- strftime(strftime_directives(example))
51
+ strftime(strftime_format(example))
38
52
  end
39
53
 
40
- def strftime_directives(example)
41
- directives = []
42
- previous_directive = nil
43
54
 
44
- terms = example.split(/\b/)
55
+ private
56
+
57
+ # Transforms the given string with example dates/times to a format string
58
+ # suitable for strftime.
59
+ def strftime_format(example)
60
+ # extract any substrings that look like times, like "23:59" or "8:37 am"
61
+ before, time_example, after = example.partition(TIME_REGEXP)
45
62
 
46
- terms.each_with_index do |term, index|
47
- directive = strftime_directive(term, previous_directive)
48
- directives << (directive || term)
63
+ # transform any date tokens to strftime directives
64
+ words = strftime_directives(before.split(/\b/)) do |token, previous_directive|
65
+ strftime_date_directive(token, previous_directive)
66
+ end
49
67
 
68
+ # transform the example time string to strftime directives
69
+ unless time_example.empty?
70
+ time_parts = time_example.scan(TIME_REGEXP).first
71
+ words += strftime_directives(time_parts) do |token, previous_directive|
72
+ strftime_time_directive(token, previous_directive)
73
+ end
74
+ end
75
+
76
+ # recursively process any remaining text
77
+ words << strftime_format(after) unless after.empty?
78
+ words.join
79
+ end
80
+
81
+ # Transforms tokens that look like date/time parts to strftime directives.
82
+ def strftime_directives(tokens)
83
+ previous_directive = nil
84
+ tokens.map do |token|
85
+ directive = yield(token, previous_directive)
50
86
  previous_directive = directive unless directive.nil?
87
+ directive || token
51
88
  end
89
+ end
90
+
91
+ def strftime_time_directive(token, previous_directive)
92
+ case token
93
+ when MERIDIAN_LOWER_REGEXP
94
+ '%P'
95
+
96
+ when MERIDIAN_UPPER_REGEXP
97
+ '%p'
98
+
99
+ when TWO_DIGIT_REGEXP
100
+ TWO_DIGIT_TIME_SUCCESSION[previous_directive] ||
101
+ case token.to_i
102
+ when OBVIOUS_24_HOUR
103
+ '%H' # 24-hour clock
104
+ else
105
+ '%I' # 12-hour clock with leading zero
106
+ end
52
107
 
53
- directives.join
108
+ when ONE_DIGIT_REGEXP
109
+ '%l' # hour without leading zero
110
+ end
54
111
  end
55
- private :strftime_directives
56
112
 
57
- def strftime_directive(term, previous_directive=nil)
58
- case term
113
+ def strftime_date_directive(token, previous_directive)
114
+ case token
59
115
  when MONTHNAMES_REGEXP
60
116
  '%B'
61
117
 
@@ -73,7 +129,7 @@ module Stamp
73
129
 
74
130
  when TWO_DIGIT_REGEXP
75
131
  # try to discern obvious intent based on the example value
76
- case term.to_i
132
+ case token.to_i
77
133
  when OBVIOUS_YEARS
78
134
  '%y'
79
135
  when OBVIOUS_MONTHS
@@ -83,22 +139,16 @@ module Stamp
83
139
  else
84
140
  # the intent isn't obvious based on the example value, so try to
85
141
  # disambiguate based on context
86
- case previous_directive
87
- when '%m', '%b', '%B' # a month
88
- '%d' # day with leading zero
89
- when '%d', '%e' # a day
90
- '%y' # two-digit year
91
- else
92
- '%m' # month
93
- end
142
+ TWO_DIGIT_DATE_SUCCESSION[previous_directive] || '%m'
94
143
  end
95
144
 
96
145
  when ONE_DIGIT_REGEXP
97
146
  '%e' # day without leading zero
98
147
  end
99
148
  end
100
- private :strftime_directive
101
149
  end
102
150
  end
103
151
 
104
- Date.send(:include, ::Stamp)
152
+
153
+ Date.send(:include, ::Stamp)
154
+ Time.send(:include, ::Stamp)
data/lib/stamp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Stamp
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 1
7
8
  - 0
8
- - 3
9
- version: 0.0.3
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jeremy Weiskotten
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-06-30 00:00:00 -04:00
17
+ date: 2011-07-05 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -55,6 +55,7 @@ extra_rdoc_files: []
55
55
  files:
56
56
  - .gitignore
57
57
  - .rvmrc
58
+ - .travis.yml
58
59
  - Gemfile
59
60
  - Gemfile.lock
60
61
  - LICENSE.txt