kronic 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kronic (0.4.1)
4
+ kronic (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/HISTORY CHANGED
@@ -1,3 +1,6 @@
1
+ 1.1.0 - 28 October 2010
2
+ * Remove dependency on strftime.js
3
+
1
4
  1.0.0 - 27 October 2010
2
5
  * Added javascript implementation
3
6
  * Committed to backwards compatibility for current API until v2
@@ -18,12 +18,10 @@ Supported formats: Today, yesterday, tomorrow, last thursday, this thursday, 14
18
18
 
19
19
  Install by grabbing the latest versions direct from github:
20
20
 
21
- curl http://github.com/xaviershay/kronic/raw/master/lib/js/strftime.js > public/javascripts/strftime.js
22
21
  curl http://github.com/xaviershay/kronic/raw/master/lib/js/kronic.js > public/javascripts/kronic.js
23
22
 
24
23
  Use with the following script:
25
24
 
26
- <script src="/javascripts/strftime.js" type="text/javascript"></script>
27
25
  <script src="/javascripts/kronic.js" type="text/javascript"></script>
28
26
  <script>
29
27
  Kronic.parse("Today");
@@ -51,7 +49,7 @@ Kronic is tested on 1.8.7, 1.9.2, Rubinius 1.1, and JRuby 1.5.1.
51
49
  rake
52
50
  open spec/kronic_spec.rb
53
51
 
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.
52
+ 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.
55
53
 
56
54
  The exact same set of specs are run again the ruby and javascript libraries, so they should be 100% compatible.
57
55
 
@@ -0,0 +1,154 @@
1
+ /* This code is a direct port of the ruby code.
2
+ * See kronic.rb for explanatory remarks.
3
+ */
4
+ var Kronic = (function() {
5
+ var DELIMITER = /[,\s]+/;
6
+ var NUMBER = /^[0-9]+$/;
7
+ var NUMBER_WITH_ORDINAL = /^([0-9]+)(st|nd|rd|th)?$/;
8
+ var ISO_8601_DATE = /^([0-9]{4})-?(1[0-2]|0?[1-9])-?(3[0-1]|[1-2][0-9]|0?[1-9])$/;
9
+
10
+ var MONTH_NAMES = ["january", "jan", "february", "feb", "march", "mar", "april", "apr", "may", "may", "june", "jun", "july", "jul", "august", "aug", "september", "sep", "october", "oct", "november", "nov", "december", "dec"];
11
+ var DAY_NAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
12
+
13
+ function trim(string) {
14
+ return string.replace(/^\s+|\s+$/g, '');
15
+ }
16
+
17
+ function map(array, func) {
18
+ var result = [];
19
+ for (x in array) {
20
+ result.push(func(array[x]));
21
+ }
22
+ return result;
23
+ }
24
+
25
+ function inject(array, initialValue, func) {
26
+ var accumulator = initialValue;
27
+ for (x in array) {
28
+ accumulator = func(accumulator, array[x]);
29
+ }
30
+ return accumulator;
31
+ }
32
+
33
+ function addDays(date, numberOfDays) {
34
+ return new Date(date * 1 + numberOfDays * 60 * 60 * 24 * 1000);
35
+ }
36
+
37
+ function titleize(str) {
38
+ return str.replace(/^\w/, function($0) { return $0.toUpperCase(); });
39
+ }
40
+
41
+ function parseNearbyDays(string, today) {
42
+ if (string == 'today') return today;
43
+ if (string == 'yesterday') return addDays(today, -1);
44
+ if (string == 'tomorrow') return addDays(today, +1);
45
+ }
46
+
47
+ function parseLastOrThisDay(string, today) {
48
+ var tokens = string.split(DELIMITER);
49
+
50
+ if (['last', 'this'].indexOf(tokens[0]) >= 0) {
51
+ var days = map([1,2,3,4,5,6,7], function(x) {
52
+ return addDays(today, tokens[0] == 'last' ? -x : x);
53
+ });
54
+
55
+ days = inject(days, {}, function(a, x) {
56
+ a[DAY_NAMES[x.getDay()].toLowerCase()] = x;
57
+ return a;
58
+ });
59
+
60
+ return days[tokens[1]];
61
+ }
62
+ }
63
+
64
+ function parseExactDay(string, today) {
65
+ var tokens = string.split(DELIMITER);
66
+ if (tokens.length >= 2) {
67
+ var matches = tokens[0].match(NUMBER_WITH_ORDINAL);
68
+ if (matches) {
69
+ return parseExactDateParts(matches[1], tokens[1], tokens[2], today);
70
+ } else {
71
+ matches = tokens[1].match(NUMBER_WITH_ORDINAL);
72
+ if (matches) {
73
+ return parseExactDateParts(matches[1], tokens[0], tokens[2], today);
74
+ } else {
75
+ return null;
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ function parseExactDateParts(rawDay, rawMonth, rawYear, today) {
82
+ var day = rawDay * 1;
83
+ var month = monthFromName(rawMonth);
84
+ var year;
85
+
86
+ if (rawYear)
87
+ year = rawYear.match(NUMBER) ? rawYear * 1 : null;
88
+ else
89
+ year = today.getYear() + 1900;
90
+
91
+ if (!(day && month && year))
92
+ return null;
93
+
94
+ var result = new Date(year, month, day);
95
+ if (result > today && !rawYear)
96
+ result = new Date(year - 1, month, day);
97
+ return result;
98
+ }
99
+
100
+ function parseIso8601Date(string) {
101
+ if (string.match(ISO_8601_DATE)) {
102
+ var tokens = map(string.split('-'), function(x) { return x * 1; });
103
+ return (new Date(tokens[0], tokens[1] - 1, tokens[2]));
104
+ }
105
+ }
106
+
107
+ function monthFromName(month) {
108
+ monthIndex = MONTH_NAMES.indexOf(month);
109
+ return monthIndex >= 0 ? Math.floor(monthIndex / 2) : null;
110
+ }
111
+
112
+ return {
113
+ parse: function(string) {
114
+ var now = Kronic.today();
115
+
116
+ string = trim(string + '').toLowerCase();
117
+ return parseNearbyDays( string, now) ||
118
+ parseLastOrThisDay(string, now) ||
119
+ parseExactDay( string, now) ||
120
+ parseIso8601Date( string);
121
+ },
122
+ format: function(date, opts) {
123
+ if (!opts)
124
+ opts = {today: Kronic.today()};
125
+
126
+ var diff = Math.floor((date * 1 - opts.today * 1) / 60 / 60 / 24 / 1000);
127
+
128
+ switch (diff) {
129
+ case -7:
130
+ case -6:
131
+ case -5:
132
+ case -4:
133
+ case -3:
134
+ case -2: return "Last " + DAY_NAMES[date.getDay()];
135
+ case -1: return "Yesterday";
136
+ case 0: return "Today";
137
+ case 1: return "Tomorrow";
138
+ case 2:
139
+ case 3:
140
+ case 4:
141
+ case 5:
142
+ case 6:
143
+ case 7: return "This " + DAY_NAMES[date.getDay()];
144
+ default:
145
+ return date.getDate() + " " +
146
+ titleize(MONTH_NAMES[date.getMonth() * 2]) + " " +
147
+ (date.getYear() + 1900);
148
+ }
149
+ },
150
+ today: function() {
151
+ return new Date();
152
+ }
153
+ };
154
+ })();
@@ -10,9 +10,7 @@ describe Kronic do
10
10
 
11
11
  @js = V8::Context.new
12
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
13
+ @js.eval(File.open(File.dirname(__FILE__) + "/../lib/js/kronic.js").read)
16
14
  @js.eval("Kronic")['today'] = proc { date(:today).to_time }
17
15
  end
18
16
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
+ - 1
7
8
  - 0
8
- - 0
9
- version: 1.0.0
9
+ version: 1.1.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-27 00:00:00 +11:00
17
+ date: 2010-10-28 00:00:00 +11:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -86,6 +86,7 @@ files:
86
86
  - spec/kronic_spec.rb
87
87
  - spec/spec_helper.rb
88
88
  - lib/kronic.rb
89
+ - lib/js/kronic.js
89
90
  - Gemfile
90
91
  - Gemfile.lock
91
92
  - README.rdoc
@@ -122,6 +123,6 @@ rubyforge_project:
122
123
  rubygems_version: 1.3.7
123
124
  signing_key:
124
125
  specification_version: 3
125
- summary: A dirt simple library for parsing human readable dates
126
+ summary: A dirt simple library for parsing and formatting human readable dates
126
127
  test_files: []
127
128