night-time 1.0.1 → 1.0.2

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/README CHANGED
@@ -27,16 +27,16 @@ SYNOPSIS
27
27
  DESCRIPTION
28
28
  * NightTime.mktime(*args)
29
29
  * NightTime.parse(text)
30
- * NightTime::Jst.parse(text)
30
+ * NightTime::Jst.parse(text, now = nil) # => a Time
31
+ * NightTime::Jst.parsedate(text) # => an Array
31
32
 
32
33
  JST
33
34
  NightTime::Jst can extract time from Japanese texts.
34
35
 
35
- jst = NightTime::Jst.new("テレビ7月8日(土)24:30~25:00")
36
- jst.parse
36
+ jst = NightTime::Jst.parsedate("テレビ7月8日(土)24:30~25:00")
37
37
  => [nil,7,8,24,30,nil]
38
38
 
39
- jst.time
39
+ jst = NightTime::Jst.parse("テレビ7月8日(土)24:30~25:00")
40
40
  => Mon Jul 09 00:30:00 +0900 2012
41
41
 
42
42
  CHANGES
@@ -3,32 +3,50 @@ require 'nkf'
3
3
 
4
4
  module NightTime
5
5
  class Jst
6
+ ######################################################################
7
+ ### Class Methods
8
+
6
9
  def self.parse(text, now = nil)
7
10
  new(text).time(now)
8
11
  end
9
12
 
13
+ def self.parsedate(text)
14
+ new(text).parse
15
+ end
16
+
17
+ ######################################################################
18
+ ### Builder
19
+
10
20
  class Build < RuntimeError
11
21
  attr_accessor :year,:month,:day,:hour,:min,:sec
12
22
  def date?; month and day; end
13
23
  def time?; hour and min; end
14
24
  def full?; date? and time?; end
15
- def to_array; [year, month, day, hour, min, sec]; end
25
+ def to_a; [year, month, day, hour, min, sec]; end
16
26
  def to_time; NightTime.mktime(year, month, day, hour||0, min||0, sec||0); end
17
27
  def inspect; "<Build: %s>" % [year,month,day,hour,min,sec].inspect; end
18
28
  end
19
29
 
30
+ class Changed < RuntimeError; end
31
+ class Completed < RuntimeError; end
32
+
33
+ ######################################################################
34
+ ### Jst class
35
+
20
36
  def initialize(text)
21
37
  @text = NKF.nkf('-Wwxm0Z0', text).gsub(/\s+/m,' ').strip
22
38
  @build = Build.new
39
+ @trace = []
23
40
  end
24
41
 
25
- def parsedate
42
+ def trace
26
43
  build!
27
- @build.to_array
44
+ return @trace
28
45
  end
29
46
 
30
47
  def parse
31
- parsedate
48
+ build!
49
+ @build.to_a
32
50
  end
33
51
 
34
52
  def time(now = nil)
@@ -64,81 +82,105 @@ module NightTime
64
82
 
65
83
  private
66
84
  def build!
67
- catch(:completed) {
68
- parse_nengappi
69
- parse_gappi
70
- parse_iso8601
71
- parse_jifunbyou
72
- parse_jifun
73
- parse_month_slash_day
74
- parse_hour_colon_min
75
- }
85
+ try :parse_nengappi
86
+ try :parse_gappi
87
+ try :parse_iso8601
88
+ try :parse_jifunbyou
89
+ try :parse_jifun
90
+ try :parse_month_slash_day
91
+ try :parse_hour_colon_min
92
+ rescue Completed
76
93
  end
77
94
 
78
95
  def parse_nengappi
79
96
  @text.scan(/(\d{4})\s*年\s*(\d{1,2})\s*月\s*(\d{1,2})\s*日/) {
80
- @build.year ||= $1.to_i
81
- @build.month ||= $2.to_i
82
- @build.day ||= $3.to_i
83
- return validate!
97
+ return observe {
98
+ @build.year ||= $1.to_i
99
+ @build.month ||= $2.to_i
100
+ @build.day ||= $3.to_i
101
+ }
84
102
  }
85
103
  end
86
104
 
87
105
  def parse_gappi
88
106
  @text.scan(/(\d{1,2})\s*月\s*(\d{1,2})\s*日/) {
89
- @build.month ||= $1.to_i
90
- @build.day ||= $2.to_i
91
- return validate!
107
+ return observe {
108
+ @build.month ||= $1.to_i
109
+ @build.day ||= $2.to_i
110
+ }
92
111
  }
93
112
  end
94
113
 
95
114
  def parse_iso8601
96
- @text.scan(/(\d{4})[-\/](\d{1,2})[-\/](\d{1,2})/) {
97
- @build.year ||= $1.to_i
98
- @build.month ||= $2.to_i
99
- @build.day ||= $3.to_i
100
- return validate!
115
+ @text.scan(/(?:^|[^\d\/])(\d{4})[-\/](\d{1,2})[-\/](\d{1,2})($|[^\d\/])/) {
116
+ (1..12).include?($2.to_i) or return false
117
+ (1..31).include?($3.to_i) or return false
118
+ return observe {
119
+ @build.year ||= $1.to_i
120
+ @build.month ||= $2.to_i
121
+ @build.day ||= $3.to_i
122
+ }
101
123
  }
102
124
  end
103
125
 
104
126
  def parse_month_slash_day
105
- @text.scan(/(\d{1,2})\/(\d{1,2})/) {
106
- @build.month ||= $1.to_i
107
- @build.day ||= $2.to_i
108
- return validate!
127
+ @text.scan(/(?:^|[^\d\/])(\d{1,2})\/(\d{1,2})($|[^\d\/])/) {
128
+ (1..12).include?($1.to_i) or return false
129
+ (1..31).include?($2.to_i) or return false
130
+ return observe {
131
+ @build.month ||= $1.to_i
132
+ @build.day ||= $2.to_i
133
+ }
109
134
  }
110
135
  end
111
136
 
112
137
  def parse_jifunbyou
113
138
  @text.scan(/(夜)?\s*(\d{1,2})\s*時\s*(\d{1,2})\s*分\s*(\d{1,2})秒/) {
114
- hour_margin = ($1 and $2.to_i < 5) ? 24 : 0
115
- @build.hour ||= hour_margin + $2.to_i
116
- @build.min ||= $3.to_i
117
- @build.sec ||= $4.to_i
118
- return validate!
139
+ return observe {
140
+ hour_margin = ($1 and $2.to_i < 5) ? 24 : 0
141
+ @build.hour ||= hour_margin + $2.to_i
142
+ @build.min ||= $3.to_i
143
+ @build.sec ||= $4.to_i
144
+ }
119
145
  }
120
146
  end
121
147
 
122
148
  def parse_jifun
123
149
  @text.scan(/(夜)?\s*(\d{1,2})\s*時\s*(\d{1,2})\s*分/) {
124
- hour_margin = ($1 and $2.to_i < 5) ? 24 : 0
125
- @build.hour ||= hour_margin + $2.to_i
126
- @build.min ||= $3.to_i
127
- return validate!
150
+ return observe {
151
+ hour_margin = ($1 and $2.to_i < 5) ? 24 : 0
152
+ @build.hour ||= hour_margin + $2.to_i
153
+ @build.min ||= $3.to_i
154
+ }
128
155
  }
129
156
  end
130
157
 
131
158
  def parse_hour_colon_min
132
159
  @text.scan(/(夜)?\s*(\d{1,2}):(\d{1,2})/) {
133
- hour_margin = ($1 and $2.to_i < 5) ? 24 : 0
134
- @build.hour ||= hour_margin + $2.to_i
135
- @build.min ||= $3.to_i
136
- return validate!
160
+ return observe {
161
+ hour_margin = ($1 and $2.to_i < 5) ? 24 : 0
162
+ @build.hour ||= hour_margin + $2.to_i
163
+ @build.min ||= $3.to_i
164
+ }
137
165
  }
138
166
  end
139
167
 
168
+ def try(method)
169
+ __send__(method)
170
+ rescue Changed
171
+ @trace << method
172
+ validate!
173
+ end
174
+
175
+ def observe(&block)
176
+ a1 = @build.to_a
177
+ block.call
178
+ a2 = @build.to_a
179
+ raise Changed if a1 != a2
180
+ end
181
+
140
182
  def validate!
141
- throw(:completed) if @build.full?
183
+ raise Completed if @build.full?
142
184
  end
143
185
  end
144
186
  end
@@ -1,3 +1,3 @@
1
1
  module NightTime
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
@@ -8,6 +8,12 @@ describe NightTime::Jst do
8
8
  NightTime::Jst.parse("2012/7/3 11:30").should == Time.mktime(2012,7,3,11,30)
9
9
  end
10
10
  end
11
+
12
+ describe ".parsedate" do
13
+ it "should return an Array" do
14
+ NightTime::Jst.parsedate("2012/7/3 11:30").should == [2012, 7, 3, 11, 30, nil]
15
+ end
16
+ end
11
17
  end
12
18
 
13
19
  describe NightTime::Jst do
@@ -28,6 +34,12 @@ describe NightTime::Jst do
28
34
  its(:time ) { should == Time.mktime(2012,7,3) }
29
35
  end
30
36
 
37
+ context "(X/X)" do
38
+ let(:text ) { "7/3" }
39
+ its(:parse) { should == [nil,7,3,nil,nil,nil] }
40
+ its(:time ) { should == Time.mktime(2012,7,3) }
41
+ end
42
+
31
43
  context "(XX月XX日)[半角]" do
32
44
  let(:text ) { "テレビ7月8日(土)24:30~25:00" }
33
45
  its(:parse) { should == [nil,7,8,24,30,nil] }
@@ -75,4 +87,66 @@ describe NightTime::Jst do
75
87
  its(:parse) { should == [nil, nil, nil, 23, 30, nil] }
76
88
  its(:time ) { should == Time.mktime(year,month,day,23,30) }
77
89
  end
90
+
91
+ ######################################################################
92
+ ### ignore range error
93
+
94
+ context "(13/X)" do
95
+ let(:text ) { "13/3" }
96
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
97
+ end
98
+
99
+ context "(X/32)" do
100
+ let(:text ) { "1/32" }
101
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
102
+ end
103
+
104
+ context "(0/X)" do
105
+ let(:text ) { "0/1" }
106
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
107
+ end
108
+
109
+ context "(X/0)" do
110
+ let(:text ) { "1/0" }
111
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
112
+ end
113
+
114
+ context "(XXXX/0/X)" do
115
+ let(:text ) { "2012/0/3" }
116
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
117
+ end
118
+
119
+ context "(XXXX/X/0)" do
120
+ let(:text ) { "2012/1/0" }
121
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
122
+ end
123
+
124
+ context "(XXXX/13/X)" do
125
+ let(:text ) { "2012/13/1" }
126
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
127
+ end
128
+
129
+ context "(XXXX/X/32)" do
130
+ let(:text ) { "2012/1/32" }
131
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
132
+ end
133
+
134
+ context "(YYYYY/MM/DD)" do
135
+ let(:text ) { "11994-04-12" }
136
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
137
+ end
138
+
139
+ ######################################################################
140
+ ### ambiguous value
141
+
142
+ context "(2012/1/1/1)" do
143
+ let(:text ) { "2012/1/1/1" }
144
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
145
+ end
146
+
147
+ context "(1/1/1)" do
148
+ let(:text ) { "1/1/1" }
149
+ its(:parse) { should == [nil,nil,nil,nil,nil,nil] }
150
+ end
151
+
78
152
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: night-time
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 1
10
- version: 1.0.1
9
+ - 2
10
+ version: 1.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - maiha
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-07-03 00:00:00 Z
18
+ date: 2012-07-04 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rspec