parsi-date 0.1.pre

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.
@@ -0,0 +1 @@
1
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in .gemspec
4
+ gemspec
@@ -0,0 +1,27 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ parsi-date (0.1.pre)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.3)
10
+ rake (0.9.2.2)
11
+ rspec (2.11.0)
12
+ rspec-core (~> 2.11.0)
13
+ rspec-expectations (~> 2.11.0)
14
+ rspec-mocks (~> 2.11.0)
15
+ rspec-core (2.11.1)
16
+ rspec-expectations (2.11.3)
17
+ diff-lcs (~> 1.1.3)
18
+ rspec-mocks (2.11.3)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ bundler
25
+ parsi-date!
26
+ rake
27
+ rspec
@@ -0,0 +1,285 @@
1
+ # encoding: utf-8
2
+
3
+ require 'date'
4
+
5
+ module Parsi
6
+ MONTHNAMES = [nil] + %w(فروردین اردیبهشت خرداد تیر مرداد شهریور مهر آبان آذر دی بهمن اسفند)
7
+ ABBR_MONTHNAMES = [nil] + %w(Far Ord Kho Tir Mor Sha Meh Abn Azr Dey Bah Esf)
8
+ DAYNAMES = %w(شنده یک‌شنده دوشنده سه‌شنده چهارشنده چنج‌شنده جمعه)
9
+ ABBR_DAYNAMES = %w(ش ۱ش ۲ش ۳ش ۴ش ۵ش ج)
10
+ [MONTHNAMES, ABBR_MONTHNAMES, DAYNAMES, ABBR_DAYNAMES].each &:freeze
11
+
12
+ class Date
13
+ include Comparable
14
+
15
+ attr_reader :year, :month, :day
16
+
17
+ DAYS_TO_FIRST_OF_MONTH = [nil, 0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336]
18
+ DAYS_IN_MONTH = [nil, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29]
19
+ JALALI_EPOCH = 1948320.5
20
+
21
+ class << self
22
+
23
+ def leap? year
24
+ ((((((year - ((year > 0) ? 474 : 473)) % 2820) + 474) + 38) * 682) % 2816) < 682
25
+ end
26
+ alias :exist? :leap?
27
+
28
+ def valid? year, month, day
29
+ return false unless year.is_a?(Fixnum) && month.is_a?(Fixnum) && day.is_a?(Fixnum)
30
+ return true if leap?(year) && month == 12 && day == 30
31
+
32
+ 1 <= month && month <= 12 && 1 <= day && day <= DAYS_IN_MONTH[month]
33
+ end
34
+
35
+ def jd jday=0
36
+ jday = jday.floor
37
+
38
+ depoch = (jday - Date.new(475, 1, 1).jd).floor
39
+ cycle = depoch / 1029983
40
+ cyear = depoch % 1029983
41
+
42
+ if cyear == 1029982
43
+ ycycle = 2820
44
+ else
45
+ aux1 = cyear / 366
46
+ aux2 = cyear % 366
47
+ ycycle = (2134 * aux1 + 2816 * aux2 + 2815) / 1028522 + aux1 + 1
48
+ end
49
+ year = ycycle + 2820 * cycle + 474
50
+ year -= 1 if year <= 0
51
+
52
+ yday = jday - Date.new(year, 1, 1).jd + 1
53
+ month = (yday <= 186) ? (yday / 31.0).ceil : ((yday - 6) / 30.0).ceil
54
+ day = (jday - Date.new(year, month, 1).jd + 1).floor
55
+ Date.new year, month, day
56
+ end
57
+
58
+ alias :civil :new
59
+
60
+ def ordinal year, ydays=1
61
+ jd = Date.new(year, 1, 1).jd + ydays - 1
62
+ Date.jd jd
63
+ end
64
+
65
+ def parse string, comp=true
66
+ # TODO: Add more parse options, for example parse '۴ام فروردین ۱۳۹۱'
67
+ m = string.match /(?<year>\d+)(\/|-| )(?<month>\d+)(\/|-| )(?<day>\d+)/
68
+ m ||= string.match /(?<year>\d+)(?<month>\d{2})(?<day>\d{2})/
69
+ if m.nil?
70
+ raise ArgumentError.new 'invalid date'
71
+ else
72
+ year, month, day = m[:year].to_i, m[:month].to_i, m[:day].to_i
73
+ if comp && m[:year].length == 2
74
+ centry = Date.today.year / 100
75
+ year = (m[:year].prepend centry.to_s).to_i
76
+ end
77
+ if Date.valid? year, month, day
78
+ Date.new year, month, day
79
+ else
80
+ raise ArgumentError.new 'invalid date'
81
+ end
82
+ end
83
+ end
84
+
85
+ def today
86
+ Date.jd ::Date.today.jd
87
+ end
88
+
89
+ def tomorrow ; today + 1 end
90
+ def yesterday; today - 1 end
91
+ end
92
+
93
+ def initialize year=0, month=1, day=1
94
+ raise ArgumentError.new 'invalid date' unless Date.valid? year, month, day
95
+ @year, @month, @day = year, month, day
96
+ end
97
+
98
+ alias :mon :month
99
+ alias :mday :day
100
+
101
+ def to_s sep='/'
102
+ "%d%s%02d%s%02d" % [year, sep, month, sep, day]
103
+ end
104
+
105
+ def inspect
106
+ "#<#{self.class}: #{to_s('-')}>"
107
+ end
108
+
109
+ def jd
110
+ @jd ||= begin
111
+ epbase = year - ((year >= 0) ? 474 : 473)
112
+ epyear = 474 + epbase % 2820
113
+
114
+ day + DAYS_TO_FIRST_OF_MONTH[month] +
115
+ (epyear * 682 - 110) / 2816 +
116
+ (epyear - 1) * 365 +
117
+ (epbase / 2820 * 1029983) +
118
+ (JALALI_EPOCH - 1) + 0.5
119
+ end
120
+ end
121
+
122
+ def mjd ; (jd - 2400001).floor end
123
+ def ld ; (jd - 2299160).floor end
124
+ def ajd ; gregorian.ajd end
125
+ def amjd ; gregorian.amjd end
126
+
127
+ def wday
128
+ (gregorian.wday + 1) % 7
129
+ end
130
+
131
+ def cwday
132
+ wday + 1
133
+ end
134
+
135
+ def yday
136
+ (jd - first_of_year.jd + 1).to_i
137
+ end
138
+
139
+ def leap?
140
+ Date.leap? year
141
+ end
142
+
143
+ def to_gregorian
144
+ ::Date.jd jd
145
+ end
146
+ alias :gregorian :to_gregorian
147
+
148
+ def strftime format='%Y/%m/%d'
149
+ format.
150
+ gsub('%%', 'PERCENT_SUBSTITUTION_MARKER').
151
+ gsub('%+', '%a %b %e %H:%M:%S %Z %Y').
152
+ gsub('%c', '%a %-d %B %Y').
153
+ gsub('%x', '%D').
154
+ gsub('%D', '%y/%m/%d').
155
+ gsub('%F', '%Y-%m-%d').
156
+ gsub('%v', '%e-%b-%Y').
157
+ gsub('%Y', year.to_s).
158
+ gsub('%C', (year / 100).to_s).
159
+ gsub('%y', (year % 100).to_s).
160
+ gsub('%m', '%02d' % month).
161
+ gsub('%_m', '% 2d' % month).
162
+ gsub('%-m', month.to_s).
163
+ gsub('%^B', '%B').
164
+ gsub('%B', Parsi::MONTHNAMES[month]).
165
+ gsub('%h', '%b').
166
+ gsub('%b', Parsi::ABBR_MONTHNAMES[month]).
167
+ gsub('%^b', Parsi::ABBR_MONTHNAMES[month].capitalize).
168
+ gsub('%d', '%02d' % day).
169
+ gsub('%e', '% 2d' % day).
170
+ gsub('%-d', day.to_s).
171
+ gsub('%j', '%03d' % yday.to_s).
172
+ gsub('%A', Parsi::DAYNAMES[wday]).
173
+ gsub('%a', Parsi::ABBR_DAYNAMES[wday]).
174
+ gsub('%u', cwday.to_s).
175
+ gsub('%w', wday.to_s).
176
+ gsub('%n', "\n").
177
+ gsub('%t', "\t").
178
+ gsub('PERCENT_SUBSTITUTION_MARKER', '%')
179
+ end
180
+
181
+ def + days
182
+ raise TypeError.new 'expected numeric' unless days.is_a? Numeric
183
+ Date.jd jd + days
184
+ end
185
+
186
+ def - days
187
+ self + -days
188
+ end
189
+
190
+ def >> monthes
191
+ raise TypeError.new 'expected numeric' unless monthes.is_a? Numeric
192
+ monthes = year * 12 + month + monthes
193
+ y = monthes / 12
194
+ m = monthes % 12
195
+ y -= 1 and m = 12 if m == 0
196
+ d = day
197
+ d -= 1 until Date.valid? y, m, d
198
+ Date.new y, m, d
199
+ end
200
+
201
+ def << monthes
202
+ self >> -monthes
203
+ end
204
+
205
+ def <=> other
206
+ if other.respond_to? :jd
207
+ jd <=> other.jd
208
+ elsif other.is_a? Numeric
209
+ jd <=> other
210
+ else
211
+ raise ArgumentError.new "comparison of #{self.class} with #{other.class} failed"
212
+ end
213
+ end
214
+
215
+ def step limit, by=1
216
+ date = self
217
+ comp_op = %w(== <= >=)[by <=> 0]
218
+ while date.send comp_op, limit
219
+ yield date
220
+ date += by
221
+ end
222
+ self
223
+ end
224
+
225
+ def upto max, &block
226
+ step max, 1, &block
227
+ end
228
+
229
+ def downto min, &block
230
+ step min, -1, &block
231
+ end
232
+
233
+ def next
234
+ self + 1
235
+ end
236
+ alias :succ :next
237
+
238
+ def next_day n=1
239
+ self + n
240
+ end
241
+
242
+ def next_month n=1
243
+ self >> n
244
+ end
245
+
246
+ def next_year n=1
247
+ self >> (n * 12)
248
+ end
249
+
250
+ def prev_day n=1
251
+ self - n
252
+ end
253
+
254
+ def prev_month n=1
255
+ self << n
256
+ end
257
+
258
+ def prev_year n=1
259
+ self << (n * 12)
260
+ end
261
+
262
+ def shanbe? ; wday == 0 end
263
+ def yekshanbe? ; wday == 1 end
264
+ def doshanbe? ; wday == 2 end
265
+ def seshanbe? ; wday == 3 end
266
+ def chaharshanbe? ; wday == 4 end
267
+ def panjshanbe? ; wday == 5 end
268
+ def jomee? ; wday == 6 end
269
+
270
+ private
271
+ def first_of_year
272
+ @first_of_year ||= Date.ordinal year
273
+ end
274
+ end
275
+ end
276
+
277
+ class Date
278
+ def to_parsi
279
+ Parsi::Date.jd jd
280
+ end
281
+ alias :to_persian :to_parsi
282
+ alias :to_jalali :to_parsi
283
+ alias :parsi :to_parsi
284
+ alias :jalali :to_parsi
285
+ end
@@ -0,0 +1,101 @@
1
+ module Parsi
2
+ class DateTime < Date
3
+ include Comparable
4
+
5
+ attr_reader :hour, :minute, :second, :offset
6
+
7
+ class << self
8
+ def valid_time? hour=0, minute=0, second=0, offset=0
9
+ if 0 <= hour && hour <= 23 &&
10
+ 0 <= minute && minute <= 59 &&
11
+ 0 <= second && second <= 59
12
+ #TODO: Add offset validation
13
+ true
14
+ else
15
+ false
16
+ end
17
+ end
18
+
19
+ def jd jd=0
20
+ date = Date.jd jd.to_i
21
+ h = (jd - jd.to_i) * 24
22
+ m = (h - h.to_i) * 60
23
+ s = (m - m.to_i) * 60
24
+ DateTime.new date.year, date.month, date.day, h.to_i, m.to_i, s.to_i
25
+ end
26
+
27
+ def now
28
+ now = ::DateTime.now
29
+ today = now.to_date.to_parsi
30
+ DateTime.new today.year, today.month, today.day, now.hour, now.minute, now.second, now.offset
31
+ end
32
+ end
33
+
34
+ def initialize year=0, month=1, day=1, hour=0, minute=0, second=0, offset=0
35
+ raise ArgumentError.new 'invalid time' unless
36
+ DateTime.valid_time? hour, minute, second
37
+
38
+ super year, month, day
39
+ @hour, @minute, @second, @offset = hour, minute, second, offset
40
+ end
41
+
42
+ def zone sep=':'
43
+ f = offset * 24.0
44
+ "%s%02d%s%02d" % [(f >= 0 ? '+' : '-'), f.floor, sep, (f % 1) * 60]
45
+ end
46
+
47
+ def to_s sep='/'
48
+ "%sT%02d:%02d:%02d%s" % [super(sep), hour, minute, second, zone]
49
+ end
50
+
51
+ def inspect
52
+ "#<#{self.class}: #{to_s('-')}>"
53
+ end
54
+
55
+ def strftime format='%Y/%m/%d %H:%M:%S'
56
+ gregorian.strftime super format
57
+ end
58
+
59
+ def to_date
60
+ Date.new year, month, day
61
+ end
62
+
63
+ def to_gregorian
64
+ @gregorian ||= begin
65
+ ::DateTime.new super.year, super.month, super.day, hour, minute, second, zone
66
+ end
67
+ end
68
+ alias :gregorian :to_gregorian
69
+
70
+ def + days
71
+ date = super
72
+ DateTime.new date.year, date.month, date.day, hour, minute, second, offset
73
+ end
74
+
75
+ def >> monthes
76
+ date = super
77
+ DateTime.new date.year, date.month, date.day, hour, minute, second, offset
78
+ end
79
+
80
+ def <=> other
81
+ if other.is_a? Date
82
+ to_gregorian <=> other.to_gregorian
83
+ elsif other.is_a? ::Date
84
+ to_gregorian <=> other
85
+ else
86
+ raise ArgumentError.new "comparison of #{self.class} with #{other.class} failed"
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ class DateTime
93
+ def to_parsi
94
+ date = super
95
+ Parsi::DateTime.new date.year, date.month, date.day, hour, minute, second, offset
96
+ end
97
+ alias :to_persian :to_parsi
98
+ alias :to_jalali :to_parsi
99
+ alias :parsi :to_parsi
100
+ alias :jalali :to_parsi
101
+ end
@@ -0,0 +1,5 @@
1
+ module Parsi
2
+ class Date
3
+ VERSION = "0.1.pre"
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+ require 'version'
3
+
4
+ Gem::Specification.new do |s|
5
+
6
+ # Description Meta...
7
+ s.name = 'parsi-date'
8
+ s.version = Parsi::Date::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.author = 'Hassan Zamani'
11
+ s.email = 'hsn.zamani@gmail.com'
12
+ s.homepage = 'http://github.com/hzamani/parsi-date'
13
+ s.summary = 'Parsi (Jalali, Iranian, Persian) date library for Ruby'
14
+ s.description = "A Parsi date library for Ruby whitch provides much of Ruby's built-in date class"
15
+
16
+
17
+ # Load Paths...
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ['lib']
22
+
23
+
24
+ # Dependencies (installed via 'bundle install')...
25
+ s.add_development_dependency("bundler")
26
+ s.add_development_dependency("rake")
27
+ s.add_development_dependency("rspec")
28
+ end
@@ -0,0 +1,66 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Parsi::Date#ajd" do
4
+ it "determines the Astronomical Julian day" do
5
+ Parsi::Date.civil(1391, 8, 6).ajd.should == Rational(4912455, 2)
6
+ end
7
+ end
8
+
9
+ describe "Parsi::Date#amjd" do
10
+ it "determines the Astronomical Modified Julian day" do
11
+ Parsi::Date.civil(1391, 8, 6).amjd.should == 56227
12
+ end
13
+ end
14
+
15
+ describe "Parsi::Date#mjd" do
16
+ it "determines the Modified Julian day" do
17
+ Parsi::Date.civil(1391, 8, 6).mjd.should == 56227
18
+ end
19
+ end
20
+
21
+ describe "Parsi::Date#ld" do
22
+ it "determines the Modified Julian day" do
23
+ Parsi::Date.civil(1391, 8, 6).ld.should == 157068
24
+ end
25
+ end
26
+
27
+ describe "Parsi::Date#year" do
28
+ it "determines the year" do
29
+ Parsi::Date.civil(1391, 8, 6).year.should == 1391
30
+ end
31
+ end
32
+
33
+ describe "Parsi::Date#yday" do
34
+ it "determines the year" do
35
+ Parsi::Date.civil(1391, 1, 17).yday.should == 17
36
+ Parsi::Date.civil(1391, 8, 6).yday.should == 222
37
+ end
38
+ end
39
+
40
+ describe "Parsi::Date#mon" do
41
+ it "determines the month" do
42
+ Parsi::Date.civil(1391, 1, 17).mon.should == 1
43
+ Parsi::Date.civil(1391, 8, 6).mon.should == 8
44
+ end
45
+ end
46
+
47
+ describe "Parsi::Date#mday" do
48
+ it "determines the day of the month" do
49
+ Parsi::Date.civil(1391, 1, 17).mday.should == 17
50
+ Parsi::Date.civil(1391, 10, 28).mday.should == 28
51
+ end
52
+ end
53
+
54
+ describe "Parsi::Date#wday" do
55
+ it "determines the week day" do
56
+ Parsi::Date.civil(1391, 1, 17).wday.should == 5
57
+ Parsi::Date.civil(1391, 8, 6).wday.should == 0
58
+ end
59
+ end
60
+
61
+ describe "Parsi::Date#cwday" do
62
+ it "determines the commercial week day" do
63
+ Parsi::Date.civil(1391, 1, 17).cwday.should == 6
64
+ Parsi::Date.civil(1391, 8, 6).cwday.should == 1
65
+ end
66
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Parsi::Date#>>" do
4
+ it "adds the number of months to a Parsi::Date" do
5
+ d = Parsi::Date.civil(1391, 2, 27) >> 10
6
+ d.should == Parsi::Date.civil(1391, 12, 27)
7
+ end
8
+
9
+ it "sets the day to the last day of a month if the day doesn't exist" do
10
+ d = Parsi::Date.civil(1391, 6, 31) >> 1
11
+ d.should == Parsi::Date.civil(1391, 7, 30)
12
+ end
13
+
14
+ it "raise a TypeError when passed a Symbol" do
15
+ lambda { Parsi::Date.civil(1391, 2, 27) >> :hello }.should raise_error(TypeError)
16
+ end
17
+
18
+ it "raise a TypeError when passed a String" do
19
+ lambda { Parsi::Date.civil(1391, 2, 27) >> "hello" }.should raise_error(TypeError)
20
+ end
21
+
22
+ it "raise a TypeError when passed a Parsi::Date" do
23
+ lambda { Parsi::Date.civil(1391, 2, 27) >> Parsi::Date.new }.should raise_error(TypeError)
24
+ end
25
+
26
+ it "raise a TypeError when passed an Object" do
27
+ lambda { Parsi::Date.civil(1391, 2, 27) >> Object.new }.should raise_error(TypeError)
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Parsi::Date#+" do
4
+ it "adds the number of days to a Parsi::Date" do
5
+ d = Parsi::Date.civil(1391, 2, 27) + 10
6
+ d.should == Parsi::Date.civil(1391, 3, 6)
7
+ end
8
+
9
+ it "adds a negative number of days to a Parsi::Date" do
10
+ d = Parsi::Date.civil(1391, 2, 27) + (-10)
11
+ d.should == Parsi::Date.civil(1391, 2, 17)
12
+ end
13
+
14
+ it "raises a TypeError when passed a Symbol" do
15
+ lambda { Parsi::Date.civil(1391, 2, 27) + :hello }.should raise_error(TypeError)
16
+ end
17
+
18
+ it "raises a TypeError when passed a String" do
19
+ lambda { Parsi::Date.civil(1391, 2, 27) + "hello" }.should raise_error(TypeError)
20
+ end
21
+
22
+ it "raises a TypeError when passed a Parsi::Date" do
23
+ lambda { Parsi::Date.civil(1391, 2, 27) + Parsi::Date.new }.should raise_error(TypeError)
24
+ end
25
+
26
+ it "raises a TypeError when passed an Object" do
27
+ lambda { Parsi::Date.civil(1391, 2, 27) + Object.new }.should raise_error(TypeError)
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require 'date'
3
+
4
+ describe "Parsi::Date#<=>" do
5
+ it "returns 0 when two dates are equal" do
6
+ (Parsi::Date.civil(1391, 4, 6) <=> Parsi::Date.civil(1391, 4, 6)).should == 0
7
+ (Parsi::Date.civil(1391, 4, 6) <=> Date.civil(2012, 6, 26)).should == 0
8
+ end
9
+
10
+ it "returns -1 when self is less than another date" do
11
+ (Parsi::Date.civil(1391, 4, 5) <=> Parsi::Date.civil(1391, 4, 6)).should == -1
12
+ (Parsi::Date.civil(1391, 4, 5) <=> Date.civil(2012, 6, 26)).should == -1
13
+ end
14
+
15
+ it "returns 1 when self is greater than another date" do
16
+ (Parsi::Date.civil(1392, 4, 7) <=> Parsi::Date.civil(1391, 4, 6)).should == 1
17
+ (Parsi::Date.civil(1391, 4, 7) <=> Date.civil(2012, 6, 26)).should == 1
18
+ end
19
+
20
+ it "returns 0 when self is equal to a Numeric" do
21
+ (Parsi::Date.civil(1391, 4, 6) <=> 2456105).should == 0
22
+ end
23
+
24
+ it "returns -1 when self is less than a Numeric" do
25
+ (Parsi::Date.civil(1391, 4, 6) <=> 2456106).should == -1
26
+ end
27
+
28
+ it "returns 1 when self is greater than a Numeric" do
29
+ (Parsi::Date.civil(1391, 4, 6) <=> 2456104).should == 1
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('../../spec_helper', __FILE__)
3
+
4
+ describe "Date constants" do
5
+ it "defines MONTHNAMES" do
6
+ Parsi::MONTHNAMES.should == [nil] + %w(فروردین اردیبهشت خرداد تیر مرداد شهریور مهر آبان آذر دی بهمن اسفند)
7
+ end
8
+
9
+ it "defines ABBR_MONTHNAMES" do
10
+ Parsi::ABBR_MONTHNAMES.should == [nil] + %w(Far Ord Kho Tir Mor Sha Meh Abn Azr Dey Bah Esf)
11
+ end
12
+
13
+ it "defines DAYNAMES" do
14
+ Parsi::DAYNAMES.should == %w(شنده یک‌شنده دوشنده سه‌شنده چهارشنده چنج‌شنده جمعه)
15
+ end
16
+
17
+ it "defines ABBR_DAYNAMES" do
18
+ Parsi::ABBR_DAYNAMES.should == %w(ش ۱ش ۲ش ۳ش ۴ش ۵ش ج)
19
+ end
20
+
21
+ it "freezes MONTHNAMES, DAYNAMES, ABBR_MONTHNAMES, ABBR_DAYSNAMES" do
22
+ [Parsi::MONTHNAMES, Parsi::DAYNAMES, Parsi::ABBR_MONTHNAMES, Parsi::ABBR_DAYNAMES].each do |ary|
23
+ ary.should be_frozen
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,68 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe Parsi::Date do
4
+ context "civil" do
5
+ it "constructs a date with arguments" do
6
+ expect { Parsi::Date.civil 1391, 8, 6 }.to_not raise_error
7
+ expect { Parsi::Date.civil 1391, 12, 30 }.to_not raise_error # 1391 is a leap year
8
+ end
9
+
10
+ it "doesn't construct dates for invalid arguments" do
11
+ expect { Parsi::Date.civil 1391, 15, 1 }.to raise_error(ArgumentError, 'invalid date')
12
+ expect { Parsi::Date.civil 1391, 0, 1 }.to raise_error(ArgumentError, 'invalid date')
13
+ expect { Parsi::Date.civil 1391, 1, 32 }.to raise_error(ArgumentError, 'invalid date')
14
+ expect { Parsi::Date.civil 1391, 2, 0 }.to raise_error(ArgumentError, 'invalid date')
15
+ expect { Parsi::Date.civil 1391, 8, 31 }.to raise_error(ArgumentError, 'invalid date')
16
+ expect { Parsi::Date.civil 1390, 12, 30 }.to raise_error(ArgumentError, 'invalid date') # 1390 is not a leap year
17
+ expect { Parsi::Date.civil 1391, 8, 31 }.to raise_error(ArgumentError, 'invalid date')
18
+
19
+ # invalid type
20
+ expect { Parsi::Date.civil '1390/1/1' }.to raise_error(ArgumentError, 'invalid date')
21
+ expect { Parsi::Date.civil 1391, '1', 9 }.to raise_error(ArgumentError, 'invalid date')
22
+ end
23
+
24
+ it "constructs a Date for 0/1/1 by default" do
25
+ date = Parsi::Date.civil
26
+ date.year.should == 0
27
+ date.month.should == 1
28
+ date.day.should == 1
29
+ end
30
+ end
31
+
32
+ context "ordinal" do
33
+ it "constructs a Date object from an ordinal date" do
34
+ Parsi::Date.ordinal(1390).should == Parsi::Date.civil(1390, 1, 1)
35
+ Parsi::Date.ordinal(1390,7).should == Parsi::Date.civil(1390, 1, 7)
36
+ Parsi::Date.ordinal(1390,100).should == Parsi::Date.civil(1390, 4, 7)
37
+ end
38
+ end
39
+
40
+ context "parse" do
41
+ it "should parse date from strings" do
42
+ ['1391/8/6', '1391-8-6', '1391 8 6', '1391 8 6', '13910806'].each do |date_string|
43
+ date = Parsi::Date.parse date_string
44
+ [date.year, date.month, date.day].should == [1391, 8, 6]
45
+ end
46
+ end
47
+
48
+ it "completes century when second arg is true" do
49
+ Date.stub(:today) { Date.new 2012, 10, 26 }
50
+ date = Parsi::Date.parse '91/8/5', true
51
+ [date.year, date.month, date.day].should == [1391, 8, 5]
52
+ end
53
+
54
+ it "should raise ArgumentError on invalid date string" do
55
+ expect { date = Parsi::Date.parse '1390/12/30' }.to raise_error(ArgumentError)
56
+ expect { date = Parsi::Date.parse 'bad date string' }.to raise_error(ArgumentError)
57
+ expect { date = Parsi::Date.parse '12-30-1390' }.to raise_error(ArgumentError)
58
+ end
59
+ end
60
+
61
+ context "#today" do
62
+ it "initialize a date object with today's attributes" do
63
+ Date.stub(:today) { Date.new 2012, 10, 26 }
64
+ date = Parsi::Date.today
65
+ [date.year, date.month, date.day].should == [1391, 8, 5]
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,38 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Parsi::Date.jd" do
4
+ it "constructs a date form given Chronological Julian day number" do
5
+ Parsi::Date.jd(2456228).should == Parsi::Date.civil(1391, 8, 6)
6
+ Parsi::Date.jd(2456229).should == Parsi::Date.civil(1391, 8, 7)
7
+ end
8
+
9
+ it "returns a Date object representing Julian day 0 if no arguments passed"do
10
+ Parsi::Date.jd.should == Parsi::Date.civil(-5335, 9, 1)
11
+ end
12
+
13
+ it "constructs a Date object if passed a negative number" do
14
+ Parsi::Date.jd(-1).should == Parsi::Date.civil(-5335, 8, 30)
15
+ end
16
+ end
17
+
18
+ describe "Parsi::Date#jd" do
19
+ it "determines the Julian day for a Date object" do
20
+ Parsi::Date.civil(1391, 8, 7).jd.should == 2456229
21
+ end
22
+ end
23
+
24
+ describe "Parsi::Date#to_gregorian" do
25
+ it "converts date to Gregorian date" do
26
+ date = Parsi::Date.civil(1391, 8, 7).to_gregorian
27
+ date.should be_a(Date)
28
+ date.should == Date.civil(2012, 10, 28)
29
+ end
30
+ end
31
+
32
+ describe "Date#to_parsi" do
33
+ it "converts date to Parsi date" do
34
+ date = Date.civil(2012, 10, 28).to_parsi
35
+ date.should be_a(Parsi::Date)
36
+ date.should == Parsi::Date.civil(1391, 8, 7)
37
+ end
38
+ end
@@ -0,0 +1,15 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Parsi::Date#leap?" do
4
+ it "returns true if a year is a leap year in the Parsi (Jalali) calendar" do
5
+ Parsi::Date.leap?(1387).should be_true
6
+ Parsi::Date.leap?(1391).should be_true
7
+ Parsi::Date.leap?(1395).should be_true
8
+ end
9
+
10
+ it "returns false if a year is not a leap year in the Parsi (Jalali) calendar" do
11
+ Parsi::Date.leap?(1390).should be_false
12
+ Parsi::Date.leap?(1392).should be_false
13
+ Parsi::Date.leap?(1400).should be_false
14
+ end
15
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Parsi::Date#step" do
4
+
5
+ it "steps forward in time" do
6
+ ds = Parsi::Date.civil(1391, 10, 11)
7
+ de = Parsi::Date.civil(1391, 9, 29)
8
+ count = 0
9
+ de.step(ds) do |d|
10
+ d.should <= ds
11
+ d.should >= de
12
+ count += 1
13
+ end
14
+ count.should == 13
15
+
16
+ count = 0
17
+ de.step(ds, 5) do |d|
18
+ d.should <= ds
19
+ d.should >= de
20
+ count += 1
21
+ end
22
+ count.should == 3
23
+
24
+ count = 0
25
+ ds.step(de) do |d|; count += 1; end
26
+ count.should == 0
27
+ end
28
+
29
+ it "steps backward in time" do
30
+ ds = Parsi::Date.civil(1390, 4, 14)
31
+ de = Parsi::Date.civil(1390, 3, 29)
32
+ count = 0
33
+ ds.step(de, -1) do |d|
34
+ d.should <= ds
35
+ d.should >= de
36
+ count += 1
37
+ end
38
+ count.should == 17
39
+
40
+ count = 0
41
+ ds.step(de, -5) do |d|
42
+ d.should <= ds
43
+ d.should >= de
44
+ count += 1
45
+ end
46
+ count.should == 4
47
+
48
+ count = 0
49
+ de.step(ds, -1) do |d|; count += 1; end
50
+ count.should == 0
51
+ end
52
+ end
@@ -0,0 +1,104 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('../../spec_helper', __FILE__)
3
+
4
+ describe "Parsi::Date#strftime" do
5
+
6
+ it "should be able to print the date" do
7
+ Parsi::Date.civil(1390, 4, 6).strftime.should == "1390/04/06"
8
+ Parsi::Date.civil(1390, 4, 6).strftime.should == Parsi::Date.civil(1390, 4, 6).to_s
9
+ end
10
+
11
+ it "should be able to print the full day name" do
12
+ Parsi::Date.civil(1390, 4, 6).strftime("%A").should == "دوشنده"
13
+ end
14
+
15
+ it "should be able to print the short day name" do
16
+ Parsi::Date.civil(1390, 4, 6).strftime("%a").should == "۲ش"
17
+ end
18
+
19
+ it "should be able to print the full month name" do
20
+ Parsi::Date.civil(1390, 4, 6).strftime("%B").should == "تیر"
21
+ end
22
+
23
+ it "should be able to print the short month name" do
24
+ Parsi::Date.civil(1390, 4, 6).strftime("%b").should == "Tir"
25
+ Parsi::Date.civil(1390, 4, 6).strftime("%h").should == "Tir"
26
+ Parsi::Date.civil(1390, 4, 6).strftime("%b").should == Parsi::Date.civil(1390, 4, 6).strftime("%h")
27
+ end
28
+
29
+ it "should be able to print the century" do
30
+ Parsi::Date.civil(1390, 4, 6).strftime("%C").should == "13"
31
+ end
32
+
33
+ it "should be able to print the month day with leading zeroes" do
34
+ Parsi::Date.civil(1390, 4, 6).strftime("%d").should == "06"
35
+ end
36
+
37
+ it "should be able to print the month day with leading spaces" do
38
+ Parsi::Date.civil(1390, 4, 6).strftime("%e").should == " 6"
39
+ end
40
+
41
+ it "should be able to print the month with leading zeroes" do
42
+ Parsi::Date.civil(1390, 4, 6).strftime("%m").should == "04"
43
+ end
44
+
45
+ it "should be able to add a newline" do
46
+ Parsi::Date.civil(1390, 4, 6).strftime("%n").should == "\n"
47
+ end
48
+
49
+ it "should be able to add a tab" do
50
+ Parsi::Date.civil(1390, 4, 6).strftime("%t").should == "\t"
51
+ end
52
+
53
+ it "should be able to show the commercial week day" do
54
+ Parsi::Date.civil(1390, 4, 10).strftime("%u").should == "7"
55
+ Parsi::Date.civil(1390, 4, 11).strftime("%u").should == "1"
56
+ end
57
+
58
+ it "should be able to show the week day" do
59
+ Parsi::Date.civil(1390, 4, 10).strftime("%w").should == "6"
60
+ Parsi::Date.civil(1390, 4, 11).strftime("%w").should == "0"
61
+ end
62
+
63
+ it "should be able to show the year in YYYY format" do
64
+ Parsi::Date.civil(1390, 4, 9).strftime("%Y").should == "1390"
65
+ end
66
+
67
+ it "should be able to show the year in YY format" do
68
+ Parsi::Date.civil(1390, 4, 9).strftime("%y").should == "90"
69
+ end
70
+
71
+ it "should be able to escape the % character" do
72
+ Parsi::Date.civil(1390, 4, 9).strftime("%%").should == "%"
73
+ end
74
+
75
+ ############################
76
+ # Specs that combine stuff #
77
+ ############################
78
+
79
+ it "should be able to print the date in full" do
80
+ Parsi::Date.civil(1390, 4, 6).strftime("%c").should == "۲ش 6 تیر 1390"
81
+ Parsi::Date.civil(1390, 4, 6).strftime("%c").should == Parsi::Date.civil(1390, 4, 6).strftime('%a %-d %B %Y')
82
+ end
83
+
84
+ it "should be able to print the date with slashes" do
85
+ Parsi::Date.civil(1390, 4, 6).strftime("%D").should == "90/04/06"
86
+ Parsi::Date.civil(1390, 4, 6).strftime("%D").should == Parsi::Date.civil(1390, 4, 6).strftime('%y/%m/%d')
87
+ end
88
+
89
+ it "should be able to print the date as YYYY-MM-DD" do
90
+ Parsi::Date.civil(1390, 4, 6).strftime("%F").should == "1390-04-06"
91
+ Parsi::Date.civil(1390, 4, 6).strftime("%F").should == Parsi::Date.civil(1390, 4, 6).strftime('%Y-%m-%d')
92
+ end
93
+
94
+ it "should be able to show the commercial week" do
95
+ Parsi::Date.civil(1390, 4, 9).strftime("%v").should == " 9-Tir-1390"
96
+ Parsi::Date.civil(1390, 4, 9).strftime("%v").should == Parsi::Date.civil(1390, 4, 9).strftime('%e-%b-%Y')
97
+ end
98
+
99
+ it "should be able to show YY/MM/DD" do
100
+ Parsi::Date.civil(1390, 4, 6).strftime("%x").should == "90/04/06"
101
+ Parsi::Date.civil(1390, 4, 6).strftime("%x").should == Parsi::Date.civil(1390, 4, 6).strftime('%y/%m/%d')
102
+ end
103
+
104
+ end
@@ -0,0 +1,13 @@
1
+ require 'parsi-date'
2
+
3
+ RSpec.configure do |config|
4
+ config.treat_symbols_as_metadata_keys_with_true_values = true
5
+ config.run_all_when_everything_filtered = true
6
+ config.filter_run :focus
7
+
8
+ # Run specs in random order to surface order dependencies. If you find an
9
+ # order dependency and want to debug it, you can fix the order by providing
10
+ # the seed, which is printed after each run.
11
+ # --seed 1234
12
+ config.order = 'random'
13
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: parsi-date
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.pre
5
+ prerelease: 4
6
+ platform: ruby
7
+ authors:
8
+ - Hassan Zamani
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: A Parsi date library for Ruby whitch provides much of Ruby's built-in
63
+ date class
64
+ email: hsn.zamani@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rspec
71
+ - Gemfile
72
+ - Gemfile.lock
73
+ - lib/parsi-date.rb
74
+ - lib/parsi-datetime.rb
75
+ - lib/version.rb
76
+ - parsi-date.gemspec
77
+ - spec/parsi-date/accessor_spec.rb
78
+ - spec/parsi-date/add_month_spec.rb
79
+ - spec/parsi-date/add_spec.rb
80
+ - spec/parsi-date/comp_spec.rb
81
+ - spec/parsi-date/constants_spec.rb
82
+ - spec/parsi-date/construction_spec.rb
83
+ - spec/parsi-date/conversion_spec.rb
84
+ - spec/parsi-date/leap_spec.rb
85
+ - spec/parsi-date/step_spec.rb
86
+ - spec/parsi-date/strftime_spec.rb
87
+ - spec/spec_helper.rb
88
+ homepage: http://github.com/hzamani/parsi-date
89
+ licenses: []
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>'
104
+ - !ruby/object:Gem::Version
105
+ version: 1.3.1
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 1.8.24
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: Parsi (Jalali, Iranian, Persian) date library for Ruby
112
+ test_files:
113
+ - spec/parsi-date/accessor_spec.rb
114
+ - spec/parsi-date/add_month_spec.rb
115
+ - spec/parsi-date/add_spec.rb
116
+ - spec/parsi-date/comp_spec.rb
117
+ - spec/parsi-date/constants_spec.rb
118
+ - spec/parsi-date/construction_spec.rb
119
+ - spec/parsi-date/conversion_spec.rb
120
+ - spec/parsi-date/leap_spec.rb
121
+ - spec/parsi-date/step_spec.rb
122
+ - spec/parsi-date/strftime_spec.rb
123
+ - spec/spec_helper.rb