kronic 0.4.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/Gemfile.lock +3 -1
- data/HISTORY +10 -6
- data/README.rdoc +43 -12
- data/Rakefile +4 -1
- data/lib/kronic.rb +4 -3
- data/spec/kronic_spec.rb +68 -53
- data/spec/spec_helper.rb +47 -0
- metadata +4 -4
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
kronic (0.4)
|
4
|
+
kronic (0.4.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
@@ -18,6 +18,7 @@ GEM
|
|
18
18
|
rspec-mocks (2.0.0.beta.22)
|
19
19
|
rspec-core (= 2.0.0.beta.22)
|
20
20
|
rspec-expectations (= 2.0.0.beta.22)
|
21
|
+
therubyracer (0.8.0.pre2)
|
21
22
|
timecop (0.3.5)
|
22
23
|
tzinfo (0.3.23)
|
23
24
|
|
@@ -29,5 +30,6 @@ DEPENDENCIES
|
|
29
30
|
activesupport
|
30
31
|
kronic!
|
31
32
|
rspec (>= 2.0.0.beta.16)
|
33
|
+
therubyracer (>= 0.8.0.pre2)
|
32
34
|
timecop
|
33
35
|
tzinfo
|
data/HISTORY
CHANGED
@@ -1,23 +1,27 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0 - 27 October 2010
|
2
|
+
* Added javascript implementation
|
3
|
+
* Committed to backwards compatibility for current API until v2
|
4
|
+
|
5
|
+
0.4.1 - 22 October 2010
|
2
6
|
* Fixed parsing of "January 1999" (returns nil, rather than raising an exception)
|
3
|
-
* Support optional commas in
|
7
|
+
* Support optional commas in delimiters: "Sep 14, 2010"
|
4
8
|
|
5
|
-
0.4.0
|
9
|
+
0.4.0 - 30 September 2010
|
6
10
|
* Support ISO 8601 dates ("2010-09-30")
|
7
11
|
* Kronic.format supports Time and DateTime as a parameter
|
8
12
|
* Ironclad guarantee it works on 1.8.7, 1.9.2, Rubinius, and JRuby
|
9
13
|
|
10
|
-
0.3.0
|
14
|
+
0.3.0 - 27 September 2010
|
11
15
|
* Support month before day ("June 14")
|
12
16
|
* Support day ordinals ("14th June")
|
13
17
|
* Use Time.zone if available
|
14
18
|
* Fix Kronic.format for ruby 1.8
|
15
19
|
|
16
|
-
0.2.1
|
20
|
+
0.2.1 - 20 September 2010
|
17
21
|
* Removed dependency on active_support, no external dependencies!
|
18
22
|
* Dates in the future with a year specified are parsed correctly
|
19
23
|
|
20
|
-
0.2.0
|
24
|
+
0.2.0 - 20 September 2010
|
21
25
|
* Support "tomorrow"
|
22
26
|
* Support "this monday"
|
23
27
|
|
data/README.rdoc
CHANGED
@@ -1,17 +1,11 @@
|
|
1
1
|
= Kronic
|
2
2
|
|
3
|
-
A dirt simple library for parsing human readable dates (Today, Yesterday, Last Monday).
|
4
|
-
|
5
|
-
== Why not Chronic or Tickle
|
6
|
-
|
7
|
-
Chronic and Tickle both parse a *heap* of formats. That's not useful to me when they fail on cases I want (14 Sep), and also not useful because I don't need times or spans. I just want to replace my calendar picker.
|
8
|
-
|
9
|
-
In addition, Kronic can take a date and give you a human readable form, neither of which Chronic nor Tickle does.
|
10
|
-
|
11
|
-
Oh yeah, Kronic is about 150 lines of code with no dependencies.
|
3
|
+
A dirt simple library for parsing human readable dates (Today, Yesterday, Last Monday). Both a ruby and a javascript implementation are included.
|
12
4
|
|
13
5
|
== Usage
|
14
6
|
|
7
|
+
=== Ruby
|
8
|
+
|
15
9
|
gem install kronic
|
16
10
|
|
17
11
|
require 'kronic'
|
@@ -20,12 +14,49 @@ Oh yeah, Kronic is about 150 lines of code with no dependencies.
|
|
20
14
|
|
21
15
|
Supported formats: Today, yesterday, tomorrow, last thursday, this thursday, 14 Sep, 14 June 2010. Any dates without a year are assumed to be in the past (that's what my app needs, so that's what it does).
|
22
16
|
|
17
|
+
=== Javascript
|
18
|
+
|
19
|
+
Install by grabbing the latest versions direct from github:
|
20
|
+
|
21
|
+
curl http://github.com/xaviershay/kronic/raw/master/lib/js/strftime.js > public/javascripts/strftime.js
|
22
|
+
curl http://github.com/xaviershay/kronic/raw/master/lib/js/kronic.js > public/javascripts/kronic.js
|
23
|
+
|
24
|
+
Use with the following script:
|
25
|
+
|
26
|
+
<script src="/javascripts/strftime.js" type="text/javascript"></script>
|
27
|
+
<script src="/javascripts/kronic.js" type="text/javascript"></script>
|
28
|
+
<script>
|
29
|
+
Kronic.parse("Today");
|
30
|
+
Kronic.format(new Date());
|
31
|
+
</script>
|
32
|
+
|
33
|
+
== Why not Chronic or Tickle
|
34
|
+
|
35
|
+
Chronic and Tickle both parse a *heap* of formats. That's not useful to me when they fail on cases I want (14 Sep), and also not useful because I don't need times or spans. I just want to replace my calendar picker.
|
36
|
+
|
37
|
+
In addition, Kronic can take a date and give you a human readable form, neither of which Chronic nor Tickle does.
|
38
|
+
|
39
|
+
Oh yeah, Kronic is about 150 lines of ruby code with no dependencies, and provides a javascript implementation.
|
40
|
+
|
23
41
|
== Compatibility
|
24
42
|
|
25
43
|
Kronic does not require ActiveSupport, but if it is present Kronic will use the current time zone. In short, everything should work as you would expect.
|
26
44
|
|
27
|
-
Kronic is tested on 1.8.7, 1.9.2, Rubinius, and JRuby.
|
45
|
+
Kronic is tested on 1.8.7, 1.9.2, Rubinius 1.1, and JRuby 1.5.1.
|
46
|
+
|
47
|
+
== Developing
|
48
|
+
|
49
|
+
git clone git://github.com/xaviershay/kronic.git
|
50
|
+
bundle install # May take a while, needs to install therubyracer/V8 to test JS
|
51
|
+
rake
|
52
|
+
open spec/kronic_spec.rb
|
53
|
+
|
54
|
+
There are comments to help you along but it is pretty basic code, so everything should make sense pretty quickly. The javascript code is a direct translation of the ruby code, and as such it is undocumented - just refer back to the ruby code. strftime.js is an external library bundled here for convenience. Do not change it.
|
55
|
+
|
56
|
+
The exact same set of specs are run again the ruby and javascript libraries, so they should be 100% compatible.
|
57
|
+
|
58
|
+
Patches welcome! Fork and send a pull request. Please follow coding conventions already in use. If +jsl+ (JSLint) is in your path, rake will run it over the javascript implementation. There are currently no warnings, please keep it that way.
|
28
59
|
|
29
|
-
==
|
60
|
+
== Status
|
30
61
|
|
31
|
-
Current release is
|
62
|
+
Current release is stable, and being used in production sites. Some I18n work is in yolk's fork, but it is lagging behind the current release. I am not using this personally. Maybe also a flag to toggle the interpretation of dates without years would be nice, but not something I need.
|
data/Rakefile
CHANGED
@@ -4,5 +4,8 @@ task :default => :spec
|
|
4
4
|
# RSpec provided helper doesn't like me, for now just run it myself
|
5
5
|
desc "Run specs"
|
6
6
|
task :spec do
|
7
|
-
|
7
|
+
commands = []
|
8
|
+
commands << "bundle exec rspec spec/*_spec.rb"
|
9
|
+
commands << "jsl -nologo -process lib/js/kronic.js" if `which jsl`.length > 0
|
10
|
+
exec commands.join(" && ")
|
8
11
|
end
|
data/lib/kronic.rb
CHANGED
@@ -23,8 +23,9 @@ class Kronic
|
|
23
23
|
end
|
24
24
|
|
25
25
|
# Public: Converts a date to a human readable string. If Time.zone is
|
26
|
-
# available and set (added by active_support and rails),
|
27
|
-
# will be used as a reference point, otherwise Date.today
|
26
|
+
# available and set (it is added by active_support and rails by default),
|
27
|
+
# Time.zone.today will be used as a reference point, otherwise Date.today
|
28
|
+
# will be used.
|
28
29
|
#
|
29
30
|
# date - The Date to be converted
|
30
31
|
# opts - The Hash options used to customize formatting
|
@@ -48,7 +49,7 @@ class Kronic
|
|
48
49
|
|
49
50
|
DELIMITER = /[,\s]+/
|
50
51
|
NUMBER = /^[0-9]+$/
|
51
|
-
NUMBER_WITH_ORDINAL = /^[0-9]+(st|nd|rd|th)?$/
|
52
|
+
NUMBER_WITH_ORDINAL = /^([0-9]+)(st|nd|rd|th)?$/
|
52
53
|
ISO_8601_DATE = /^([0-9]{4})-?(1[0-2]|0?[1-9])-?(3[0-1]|[1-2][0-9]|0?[1-9])$/
|
53
54
|
|
54
55
|
MONTH_NAMES = Date::MONTHNAMES.zip(Date::ABBR_MONTHNAMES).flatten.compact.map {|x|
|
data/spec/kronic_spec.rb
CHANGED
@@ -1,18 +1,37 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Kronic do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
extend KronicMatchers
|
5
|
+
|
6
|
+
if js_supported?
|
7
|
+
# JRuby cannot currently run the specs against the JS implementation
|
8
|
+
before :all do
|
9
|
+
reset_timezone
|
10
|
+
|
11
|
+
@js = V8::Context.new
|
12
|
+
@js['alert'] = proc {|s| puts s.inspect } # For debugging, not used normally
|
13
|
+
%w(strftime kronic).each do |file|
|
14
|
+
@js.eval(File.open(File.dirname(__FILE__) + "/../lib/js/#{file}.js").read)
|
15
|
+
end
|
16
|
+
@js.eval("Kronic")['today'] = proc { date(:today).to_time }
|
7
17
|
end
|
8
18
|
end
|
9
19
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
20
|
+
before :each do
|
21
|
+
reset_timezone
|
22
|
+
Timecop.freeze(Time.utc(
|
23
|
+
date(:today).year,
|
24
|
+
date(:today).month,
|
25
|
+
date(:today).day
|
26
|
+
))
|
14
27
|
end
|
15
28
|
|
29
|
+
after :each do
|
30
|
+
Timecop.return
|
31
|
+
end
|
32
|
+
|
33
|
+
# A constant set of dates are used for testing, the current system time is frozen
|
34
|
+
# to date(:today) for the duration of each test.
|
16
35
|
def self.date(key)
|
17
36
|
{
|
18
37
|
:today => Date.new(2010, 9, 18),
|
@@ -25,53 +44,44 @@ describe Kronic do
|
|
25
44
|
end
|
26
45
|
def date(key); self.class.date(key); end;
|
27
46
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
47
|
+
# it_should_parse and it_should_format macros are defined in spec/spec_helper.rb
|
48
|
+
it_should_parse('Today', date(:today))
|
49
|
+
it_should_parse(:today, date(:today))
|
50
|
+
it_should_parse('today', date(:today))
|
51
|
+
it_should_parse(' Today', date(:today))
|
52
|
+
it_should_parse('Yesterday', date(:today) - 1)
|
53
|
+
it_should_parse('Tomorrow', date(:today) + 1)
|
54
|
+
it_should_parse('Last Monday', date(:last_monday))
|
55
|
+
it_should_parse('This Monday', date(:next_monday))
|
56
|
+
it_should_parse('4 Sep', date(:sep_4))
|
57
|
+
it_should_parse('4 Sep', date(:sep_4))
|
58
|
+
it_should_parse('4 September', date(:sep_4))
|
59
|
+
it_should_parse('20 Sep', date(:sep_20))
|
60
|
+
it_should_parse('28 Sep 2010', date(:sep_28))
|
61
|
+
it_should_parse('14 Sep 2008', Date.new(2008, 9, 14))
|
62
|
+
it_should_parse('14th Sep 2008', Date.new(2008, 9, 14))
|
63
|
+
it_should_parse('23rd Sep 2008', Date.new(2008, 9, 23))
|
64
|
+
it_should_parse('September 14 2008', Date.new(2008, 9, 14))
|
65
|
+
it_should_parse('Sep 14, 2008', Date.new(2008, 9, 14))
|
66
|
+
it_should_parse('14 Sep, 2008', Date.new(2008, 9, 14))
|
67
|
+
it_should_parse('Sep 4th', date(:sep_4))
|
68
|
+
it_should_parse('September 4', date(:sep_4))
|
69
|
+
it_should_parse('2008-09-04', Date.new(2008, 9, 4))
|
70
|
+
it_should_parse('2008-9-4', Date.new(2008, 9, 4))
|
71
|
+
it_should_parse('bogus', nil)
|
72
|
+
it_should_parse('14', nil)
|
73
|
+
it_should_parse('14 bogus in', nil)
|
74
|
+
it_should_parse('14 June oen', nil)
|
75
|
+
it_should_parse('January 1999', nil)
|
76
|
+
it_should_parse('Last M', nil)
|
38
77
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
should_parse('This Monday', date(:next_monday))
|
47
|
-
should_parse('4 Sep', date(:sep_4))
|
48
|
-
should_parse('4 Sep', date(:sep_4))
|
49
|
-
should_parse('4 September', date(:sep_4))
|
50
|
-
should_parse('20 Sep', date(:sep_20))
|
51
|
-
should_parse('28 Sep 2010', date(:sep_28))
|
52
|
-
should_parse('14 Sep 2008', Date.new(2008, 9, 14))
|
53
|
-
should_parse('14th Sep 2008', Date.new(2008, 9, 14))
|
54
|
-
should_parse('23rd Sep 2008', Date.new(2008, 9, 23))
|
55
|
-
should_parse('September 14 2008', Date.new(2008, 9, 14))
|
56
|
-
should_parse('Sep 14, 2008', Date.new(2008, 9, 14))
|
57
|
-
should_parse('14 Sep, 2008', Date.new(2008, 9, 14))
|
58
|
-
should_parse('Sep 4th', date(:sep_4))
|
59
|
-
should_parse('September 4', date(:sep_4))
|
60
|
-
should_parse('2008-09-04', Date.new(2008, 9, 4))
|
61
|
-
should_parse('2008-9-4', Date.new(2008, 9, 4))
|
62
|
-
should_parse('bogus', nil)
|
63
|
-
should_parse('14', nil)
|
64
|
-
should_parse('14 bogus in', nil)
|
65
|
-
should_parse('14 June oen', nil)
|
66
|
-
should_parse('January 1999', nil)
|
67
|
-
|
68
|
-
should_format('Today', date(:today))
|
69
|
-
should_format('Yesterday', date(:today) - 1)
|
70
|
-
should_format('Tomorrow', date(:today) + 1)
|
71
|
-
should_format('Last Monday', date(:last_monday))
|
72
|
-
should_format('This Monday', date(:next_monday))
|
73
|
-
should_format('14 September 2008', Date.new(2008, 9, 14))
|
74
|
-
should_format('14 September 2008', Time.utc(2008, 9, 14))
|
78
|
+
it_should_format('Today', date(:today))
|
79
|
+
it_should_format('Yesterday', date(:today) - 1)
|
80
|
+
it_should_format('Tomorrow', date(:today) + 1)
|
81
|
+
it_should_format('Last Monday', date(:last_monday))
|
82
|
+
it_should_format('This Monday', date(:next_monday))
|
83
|
+
it_should_format('14 September 2008', Date.new(2008, 9, 14))
|
84
|
+
it_should_format('14 September 2008', Time.utc(2008, 9, 14))
|
75
85
|
|
76
86
|
describe 'timezone support' do
|
77
87
|
before :all do
|
@@ -97,4 +107,9 @@ describe Kronic do
|
|
97
107
|
Kronic.format(date(:today)).should == "Today"
|
98
108
|
end
|
99
109
|
end
|
110
|
+
|
111
|
+
def reset_timezone
|
112
|
+
Time.zone = nil
|
113
|
+
ENV['TZ'] = "Australia/Melbourne"
|
114
|
+
end
|
100
115
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,16 @@ require 'rspec'
|
|
2
2
|
require 'timecop'
|
3
3
|
require 'active_support/core_ext/integer/time'
|
4
4
|
require 'active_support/core_ext/time/zones'
|
5
|
+
require 'active_support/core_ext/time/calculations'
|
6
|
+
require 'active_support/core_ext/date/conversions' # For nicer spec fail output
|
7
|
+
|
8
|
+
$js_loaded = begin
|
9
|
+
require 'v8'
|
10
|
+
true
|
11
|
+
rescue LoadError => e
|
12
|
+
# Can't run JS specs
|
13
|
+
false
|
14
|
+
end
|
5
15
|
|
6
16
|
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
|
7
17
|
require 'kronic'
|
@@ -21,3 +31,40 @@ module MethodVisibility
|
|
21
31
|
end
|
22
32
|
end
|
23
33
|
end
|
34
|
+
|
35
|
+
module KronicMatchers
|
36
|
+
def it_should_parse(string, date)
|
37
|
+
it "should parse '#{string}'" do
|
38
|
+
Kronic.parse(string).should == date
|
39
|
+
end
|
40
|
+
|
41
|
+
if js_supported?
|
42
|
+
it "should parse '#{string}' (JS)" do
|
43
|
+
x = @js.evaluate("Kronic").parse(string)
|
44
|
+
|
45
|
+
if x.is_a?(Time)
|
46
|
+
x = x.to_date
|
47
|
+
Date.new(x.year, x.month, x.day).should == date
|
48
|
+
else
|
49
|
+
x.should == date
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def it_should_format(string, date)
|
56
|
+
it "should format '#{string}'" do
|
57
|
+
Kronic.format(date).should == string
|
58
|
+
end
|
59
|
+
|
60
|
+
if js_supported?
|
61
|
+
it "should format '#{string}' (JS)" do
|
62
|
+
@js.evaluate("Kronic").format(date.to_time).should == string
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def js_supported?
|
69
|
+
$js_loaded
|
70
|
+
end
|
metadata
CHANGED
@@ -3,10 +3,10 @@ name: kronic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
|
-
- 0
|
7
|
-
- 4
|
8
6
|
- 1
|
9
|
-
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Xavier Shay
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-27 00:00:00 +11:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|