stamp 0.0.3 → 0.1.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.
- data/.travis.yml +9 -0
- data/Gemfile.lock +1 -1
- data/features/stamp.feature +29 -5
- data/features/step_definitions/stamp_steps.rb +16 -5
- data/lib/stamp.rb +81 -31
- data/lib/stamp/version.rb +1 -1
- metadata +4 -3
data/.travis.yml
ADDED
data/Gemfile.lock
CHANGED
data/features/stamp.feature
CHANGED
@@ -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
|
-
@
|
37
|
-
Scenario Outline:
|
38
|
-
Given the
|
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
|
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
|
-
|
3
|
-
|
4
|
-
|
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
|
-
@
|
19
|
+
@stamped = @target.stamp(example)
|
9
20
|
end
|
10
21
|
|
11
22
|
Then /^I produce "([^"]*)"$/ do |expected|
|
12
|
-
assert_equal expected, @
|
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
|
-
|
23
|
+
TIME_REGEXP = /(\d{1,2})(:)(\d{2})(\s*)(:)?(\d{2})?(\s*)?([ap]m)?/i
|
27
24
|
|
28
|
-
|
29
|
-
|
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(
|
51
|
+
strftime(strftime_format(example))
|
38
52
|
end
|
39
53
|
|
40
|
-
def strftime_directives(example)
|
41
|
-
directives = []
|
42
|
-
previous_directive = nil
|
43
54
|
|
44
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
108
|
+
when ONE_DIGIT_REGEXP
|
109
|
+
'%l' # hour without leading zero
|
110
|
+
end
|
54
111
|
end
|
55
|
-
private :strftime_directives
|
56
112
|
|
57
|
-
def
|
58
|
-
case
|
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
|
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
|
-
|
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
|
-
|
152
|
+
|
153
|
+
Date.send(:include, ::Stamp)
|
154
|
+
Time.send(:include, ::Stamp)
|
data/lib/stamp/version.rb
CHANGED
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
|
-
|
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-
|
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
|