todoist_date_time 0.2.1

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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg
2
+ nbproject
3
+ coverage
4
+ rdoc
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Kazuhiro Hiramatsu
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,26 @@
1
+ = todoist_date_time
2
+
3
+ String class extension which parses date and time literals into DateTime instances using same syntax as http://todoist.com.
4
+
5
+
6
+ == Examples:
7
+
8
+ "today @12".to_tddatetime
9
+ => Mon, 25 Jan 2010 12:00:00 +0000
10
+
11
+ "april/4 at 9:34".to_tddatetime
12
+ => Sun, 04 Apr 2010 09:34:00 +0000
13
+
14
+ "monday".to_tddatetime
15
+ => Mon, 25 Jan 2010 00:00:00 +0000
16
+
17
+
18
+ == TODO
19
+
20
+ - write full documentation of acceptable input syntax and expected results
21
+
22
+
23
+
24
+ == Copyright
25
+
26
+ Copyright (c) 2009 Kazuhiro Hiramatsu. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "todoist_date_time"
8
+ gem.summary = %Q{Parser of Todoist (http://todoist.com) datetime syntax}
9
+ gem.description = %Q{Add into String class method which converts string value written in Todoist (http://todoist.com) datetime syntax into valid DateTime instance}
10
+ gem.email = "kaz_u@wp.pl"
11
+ gem.homepage = "http://github.com/kazuhiro/todoist_date_time"
12
+ gem.authors = ["Kazuhiro Hiramatsu"]
13
+ gem.add_dependency "activesupport", ">= 2.1.2"
14
+ gem.add_development_dependency "rspec", ">= 1.2.9"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'spec/rake/spectask'
23
+ Spec::Rake::SpecTask.new(:spec) do |spec|
24
+ spec.libs << 'lib' << 'spec'
25
+ spec.spec_files = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.pattern = 'spec/**/*_spec.rb'
31
+ spec.rcov = true
32
+ end
33
+
34
+ task :spec => :check_dependencies
35
+
36
+ task :default => :spec
37
+
38
+ require 'rake/rdoctask'
39
+ Rake::RDocTask.new do |rdoc|
40
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
+
42
+ rdoc.rdoc_dir = 'rdoc'
43
+ rdoc.title = "todoist_date_time #{version}"
44
+ rdoc.rdoc_files.include('README*')
45
+ rdoc.rdoc_files.include('lib/**/*.rb')
46
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.1
@@ -0,0 +1,128 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+
4
+
5
+ module TodoistDateTime
6
+ DATE_PARTS_SEPARATORS = [".", "-", " ", "/"]
7
+ DATE_PARTS_SEPARATORS_REGEXP = Regexp.new(
8
+ "(" +
9
+ self::DATE_PARTS_SEPARATORS.map{ |elem| Regexp.escape(elem)}.join("|") +
10
+ ")")
11
+
12
+ TIME_FROM_DATE_SEPARATORS = ["@", " @ ", "@ ", " @" , " at ", " at"]
13
+ TIME_FROM_DATE_SEPARATORS_REGEXP = Regexp.new(
14
+ "(" +
15
+ self::TIME_FROM_DATE_SEPARATORS.map{ |elem| Regexp.escape(elem)}.join("|") +
16
+ ")")
17
+
18
+
19
+ class InvalidInput < ArgumentError
20
+ # Creates an instance of InvalidInput
21
+ def initialize(input)
22
+ super('unparsable datetime string given: ' + input)
23
+ end
24
+ end
25
+
26
+
27
+ module String
28
+ # Cast given date and time string into DateTime instance
29
+ # ===== Example
30
+ # "monday".to_tddatetime
31
+ # # => Mon, 25 Jan 2010 00:00:00 +0000
32
+ def to_datetime_like_todoist
33
+ parse_date(to_s)
34
+ end
35
+
36
+ alias :to_tddatetime :to_datetime_like_todoist
37
+
38
+
39
+ private
40
+
41
+ def parse_date(datetime_string)
42
+ date_string, _, time_string = datetime_string.split(
43
+ TodoistDateTime::TIME_FROM_DATE_SEPARATORS_REGEXP).map{ |element| element.strip.downcase }
44
+
45
+
46
+ datetime_object = case(date_string)
47
+
48
+ when /^tod/:
49
+ Date.today.to_datetime
50
+
51
+ when /^tom/:
52
+ DateTime.tomorrow
53
+
54
+ when /^yes/:
55
+ DateTime.yesterday
56
+
57
+ # example: +5, -3
58
+ when /^(\+|\-){1}[0-9]+$/
59
+ Date.today.to_datetime + date_string.to_i.days
60
+
61
+ when /^[a-z]+$/
62
+ day_idx = Date::DAYNAMES.index(
63
+ Date::DAYNAMES.find{ |month| month =~ Regexp.new("^" + date_string, Regexp::IGNORECASE) })
64
+
65
+ unless day_idx.nil?
66
+ datetime_object = Date.today.to_datetime
67
+ datetime_object += 1.day until datetime_object.wday == day_idx or datetime_object.wday == day_idx
68
+ datetime_object
69
+ else
70
+ raise InvalidInput.new(datetime_string)
71
+ end
72
+
73
+ # example: 4/1, 5/5, 2/5 YYYY
74
+ # or
75
+ # example: december, december.5, december.5 2009, 12.december, 12.december.2009, 1.12.2009, 1.12
76
+ when Regexp.new(
77
+ "^([0-9]{1,2}){1}" +
78
+ TodoistDateTime::DATE_PARTS_SEPARATORS_REGEXP.source +
79
+ "*([0-9]{1,2})?" +
80
+ TodoistDateTime::DATE_PARTS_SEPARATORS_REGEXP.source +
81
+ "*([0-9]{4})?$", Regexp::IGNORECASE),
82
+ # or
83
+ Regexp.new(
84
+ "^([0-9]{1,2}|[a-z]{1,9})" +
85
+ TodoistDateTime::DATE_PARTS_SEPARATORS_REGEXP.source +
86
+ "+([0-9]{1,2}|[a-z]{1,9})" +
87
+ TodoistDateTime::DATE_PARTS_SEPARATORS_REGEXP.source +
88
+ "*([0-9]{4})?$", Regexp::IGNORECASE)
89
+
90
+ parts = date_string.split(
91
+ TodoistDateTime::DATE_PARTS_SEPARATORS_REGEXP
92
+ ).map { |elem|
93
+ elem.strip
94
+ }.reject { |elem|
95
+ elem.strip.length == 0 or TodoistDateTime::DATE_PARTS_SEPARATORS.include?(elem)
96
+ }
97
+
98
+ unless Date::MONTHNAMES.include?(parts[0]) or Date::ABBR_MONTHNAMES.include?(parts[0]) or parts[0] =~ /([0-9]{1,2})/
99
+ parts[0] = Date::MONTHNAMES.find{ |month| month =~ Regexp.new("^" + parts[0], Regexp::IGNORECASE) unless month.nil? }
100
+ end
101
+
102
+ DateTime.parse( parts[1].to_s + "." + parts[0].to_s + "." + (parts.count == 3 ? parts[2].to_s : Date.today.year).to_s )
103
+
104
+ else
105
+ begin
106
+ DateTime.parse(date_string)
107
+ rescue
108
+ raise InvalidInput.new(datetime_string)
109
+ end
110
+ end
111
+
112
+ case(time_string)
113
+ when Regexp.new("^([0-9]{1,2}):?([0-9]{1,2})$")
114
+ tmp_hours, tmp_minutes = time_string.split(":")
115
+ datetime_object += tmp_hours.to_i.hours
116
+ datetime_object += tmp_minutes.to_i.minutes unless tmp_minutes.nil?
117
+ end
118
+
119
+ datetime_object
120
+ end
121
+
122
+ end
123
+ end
124
+
125
+
126
+ class String
127
+ include TodoistDateTime::String
128
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'todoist_date_time'
4
+ require 'rubygems'
5
+ require 'active_support'
6
+ require 'spec'
7
+ require 'spec/autorun'
8
+
9
+ Spec::Runner.configure do |config|
10
+
11
+ end
@@ -0,0 +1,169 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+
4
+ describe "TodoistDateTime" do
5
+ before(:all) do
6
+ @monthnames = Date::MONTHNAMES.map{ |month| month.downcase unless month.nil? }
7
+ @abbr_monthnames = Date::ABBR_MONTHNAMES.map{ |month| month.downcase unless month.nil? }
8
+ @daynames = Date::DAYNAMES.map{ |month| month.downcase }
9
+ @abbr_daynames = Date::ABBR_DAYNAMES.map{ |month| month.downcase}
10
+
11
+ @date_parts_separators = TodoistDateTime::DATE_PARTS_SEPARATORS
12
+ @time_from_date_separators = TodoistDateTime::TIME_FROM_DATE_SEPARATORS
13
+ end
14
+
15
+
16
+ describe "pointers of date" do
17
+ before(:all) do
18
+ @yesterday = Date.yesterday
19
+ @today = Date.today
20
+ @tomorrow = Date.tomorrow
21
+ end
22
+
23
+ it "should parse each week day name as nearly date which it will be" do
24
+ @daynames.each_with_index do |month, day_idx|
25
+ expected_date = @today
26
+ expected_date += 1.day until expected_date.wday == day_idx
27
+
28
+ #day.to_tddatetime.should == expected_date
29
+ @daynames[day_idx].to_tddatetime.should == expected_date
30
+ @abbr_daynames[day_idx].to_tddatetime == expected_date
31
+ end
32
+ end
33
+
34
+ it "should parse begining letters of each week day name as nearly date which it will be" do
35
+ @daynames.each do |month|
36
+ month.chars.to_a.each_with_index do |char, char_idx| # build dayname char by char and test each one
37
+ month = @daynames.find{ |month| month =~ Regexp.new("^" + month[0..char_idx], Regexp::IGNORECASE) }
38
+
39
+ expected_date = @today
40
+ expected_date += 1.day until expected_date.wday == @daynames.index(month)
41
+ month[0..char_idx].to_tddatetime.should == expected_date
42
+ end
43
+ end
44
+ end
45
+
46
+ it "should throw parse error when no date expression string is given" do
47
+ lambda{ "lorem ipsum".to_tddatetime }.should raise_error
48
+ lambda{ "lorem".to_tddatetime }.should raise_error
49
+ end
50
+
51
+ it "should parse positive number as date which will come after given number of days" do
52
+ num = rand(10)
53
+ "+#{num}".to_tddatetime.should == @today + num.days
54
+ end
55
+
56
+ it "should parse negative number as date which will was given number of days ago" do
57
+ num = rand(10)
58
+ "-#{num}".to_tddatetime.should == @today - num.days
59
+ end
60
+
61
+ it "should parse 'tod*' as current date" do
62
+ expected_day = @today
63
+
64
+ "tod".to_tddatetime.should == expected_day
65
+ "toda".to_tddatetime.should == expected_day
66
+ "today".to_tddatetime.should == expected_day
67
+ end
68
+
69
+ it "should parse 'tom*' as following day's date" do
70
+ expected_day = @today + 1.day
71
+
72
+ "tom".to_tddatetime.should == expected_day
73
+ "tom".to_tddatetime.should == expected_day
74
+ "tomo".to_tddatetime.should == expected_day
75
+ "tomor".to_tddatetime.should == expected_day
76
+ "tomorr".to_tddatetime.should == expected_day
77
+ "tomorro".to_tddatetime.should == expected_day
78
+ "tomorrow".to_tddatetime.should == expected_day
79
+ end
80
+
81
+ it "should parse 'yes*' as previous day's date" do
82
+ expected_day = @today - 1.day
83
+
84
+ "yes".to_tddatetime.should == expected_day
85
+ "yest".to_tddatetime.should == expected_day
86
+ "yester".to_tddatetime.should == expected_day
87
+ "yesterd".to_tddatetime.should == expected_day
88
+ "yesterda".to_tddatetime.should == expected_day
89
+ "yesterday".to_tddatetime.should == expected_day
90
+ end
91
+
92
+ it "should expand date with month abbreviation to full date in upcoming (given) month" do
93
+ @monthnames.each do |month|
94
+ next if month.nil?
95
+
96
+ month.chars.to_a.each_with_index do |char, char_idx| # build dayname char by char and test each one
97
+ month = @monthnames.find{ |month| month =~ Regexp.new("^" + month[0..char_idx], Regexp::IGNORECASE) unless month.nil? }
98
+ expected_date = @today
99
+ expected_date += 1.month until expected_date.month == @monthnames.index(month)
100
+ (month[0..char_idx] + "/" + expected_date.day.to_s + "/" + expected_date.year.to_s).to_tddatetime.should == expected_date
101
+ end
102
+ end
103
+ end
104
+
105
+ it "should parse 'april/1', 'april/1/2009', '4/1', 4/1/2009', '1/april', '1/april/2009' as 01.04 in YYYY or 2009" do
106
+ @date_parts_separators.each do |date_separator|
107
+ @monthnames.each_index do |month_idx|
108
+ next if month_idx == 0 # first month in Date::MONTHNAMES is a nil
109
+
110
+ current_year = @today.year
111
+ expected_date = DateTime.parse("01.#{month_idx}.#{current_year}")
112
+
113
+ month = @monthnames[month_idx]
114
+ short_month = @abbr_monthnames[month_idx]
115
+
116
+ Array.new([
117
+ # month name first: april/1, april/1/2009
118
+ [month, 1], [month, 1, current_year],
119
+
120
+ # short month name first: apr/1, apr/1/2009
121
+ [short_month, 1], [short_month, 1, current_year],
122
+
123
+ # month name second: 1/april, 1/april/2009
124
+ [1, month], [1, month, current_year],
125
+
126
+ # short month name second: 1/apr, 1/apr/2009
127
+ [1, short_month], [1, short_month, current_year],
128
+
129
+ # month index first: 4/1, 4/1/2009
130
+ [month_idx, 1], [month_idx, 1, current_year]
131
+ ]).each do |date_array|
132
+ # build a date string from array using given separator and compare it with expectation
133
+ date_array.join(date_separator).to_tddatetime.should == expected_date
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ describe "pointers of time" do
141
+ it "should parse 'friday @12:10', 'fri at 12:10' as next friday at 12 hours and 10 minutes" do
142
+ expected_date = DateTime.parse(Date.today.to_s + " 12:10")
143
+ expected_date += 1.day until expected_date.wday == @daynames.find_index("friday")
144
+
145
+ @time_from_date_separators.each do |time_separator|
146
+ ("friday" + time_separator + "12:10").to_tddatetime.should == expected_date
147
+ end
148
+ end
149
+
150
+ it "should raise an exception when only time given" do
151
+ lambda { "@12:10".to_tddatetime }.should raise_exception ArgumentError
152
+ end
153
+ end
154
+
155
+ describe "pointers of date and time" do
156
+ before(:all) do
157
+ @expected_date = DateTime.parse("01.04.2009 12:10")
158
+ end
159
+
160
+ it "should parse '1. april 2009 at 12:10' as 01.04.2009 at 12 hours and 10 minutes" do
161
+ "1. april 2009 at 12:10".to_tddatetime.should == @expected_date
162
+ end
163
+
164
+ it "should parse '4/1/2009 at 12:10' as 01.04.2009 at 12 hours and 10 minutes" do
165
+ "4/1/2009 at 12:10".to_tddatetime.should == @expected_date
166
+ end
167
+ end
168
+
169
+ end
@@ -0,0 +1,57 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{todoist_date_time}
8
+ s.version = "0.2.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Kazuhiro Hiramatsu"]
12
+ s.date = %q{2010-02-01}
13
+ s.description = %q{Add into String class method which converts string value written in Todoist (http://todoist.com) datetime syntax into valid DateTime instance}
14
+ s.email = %q{kaz_u@wp.pl}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "lib/todoist_date_time.rb",
26
+ "spec/spec.opts",
27
+ "spec/spec_helper.rb",
28
+ "spec/todoist_date_time_spec.rb",
29
+ "todoist_date_time.gemspec"
30
+ ]
31
+ s.homepage = %q{http://github.com/kazuhiro/todoist_date_time}
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.3.5}
35
+ s.summary = %q{Parser of Todoist (http://todoist.com) datetime syntax}
36
+ s.test_files = [
37
+ "spec/spec_helper.rb",
38
+ "spec/todoist_date_time_spec.rb"
39
+ ]
40
+
41
+ if s.respond_to? :specification_version then
42
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
+ s.specification_version = 3
44
+
45
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
46
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.1.2"])
47
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
48
+ else
49
+ s.add_dependency(%q<activesupport>, [">= 2.1.2"])
50
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
51
+ end
52
+ else
53
+ s.add_dependency(%q<activesupport>, [">= 2.1.2"])
54
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
55
+ end
56
+ end
57
+
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: todoist_date_time
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Kazuhiro Hiramatsu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-01 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.1.2
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.9
34
+ version:
35
+ description: Add into String class method which converts string value written in Todoist (http://todoist.com) datetime syntax into valid DateTime instance
36
+ email: kaz_u@wp.pl
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.rdoc
44
+ files:
45
+ - .gitignore
46
+ - LICENSE
47
+ - README.rdoc
48
+ - Rakefile
49
+ - VERSION
50
+ - lib/todoist_date_time.rb
51
+ - spec/spec.opts
52
+ - spec/spec_helper.rb
53
+ - spec/todoist_date_time_spec.rb
54
+ - todoist_date_time.gemspec
55
+ has_rdoc: true
56
+ homepage: http://github.com/kazuhiro/todoist_date_time
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --charset=UTF-8
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.5
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Parser of Todoist (http://todoist.com) datetime syntax
83
+ test_files:
84
+ - spec/spec_helper.rb
85
+ - spec/todoist_date_time_spec.rb