jalali-date 0.3.7

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a6cf12c626b443c3634bd78cb2e329ddf5b01ef4f907f7b16503a71bdafd4cd4
4
+ data.tar.gz: c9c43f0171b726aa0c6e9fbc3f607c3b6883e01f61a8a9abdda9c0d8636c021a
5
+ SHA512:
6
+ metadata.gz: 4b813c10502d8adf45e6cf11ea3bc278187f69acfa19b26ce5590c58c902442396e97a369598d584646056611d6ea3c6c2d696955e04b79bdd0e741ead43fb8b
7
+ data.tar.gz: 68a795aff57af3404af120fc3ea22f256186c2c8781665a8406d30be4410bc4fe375dc06732e2007081248b6f5767090a61a40138f3b320c211db60f2d2d5aa9
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ .idea/
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm: 2.4
3
+ script: rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in jalalidate.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jalali-date (0.3.7)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.6.2)
10
+ rspec (3.13.2)
11
+ rspec-core (~> 3.13.0)
12
+ rspec-expectations (~> 3.13.0)
13
+ rspec-mocks (~> 3.13.0)
14
+ rspec-core (3.13.6)
15
+ rspec-support (~> 3.13.0)
16
+ rspec-expectations (3.13.5)
17
+ diff-lcs (>= 1.2.0, < 2.0)
18
+ rspec-support (~> 3.13.0)
19
+ rspec-mocks (3.13.8)
20
+ diff-lcs (>= 1.2.0, < 2.0)
21
+ rspec-support (~> 3.13.0)
22
+ rspec-support (3.13.7)
23
+
24
+ PLATFORMS
25
+ ruby
26
+ x86_64-linux
27
+
28
+ DEPENDENCIES
29
+ bundler (>= 1.16)
30
+ jalali-date!
31
+ rspec (~> 3.0)
32
+
33
+ CHECKSUMS
34
+ diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
35
+ jalali-date (0.3.7)
36
+ rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
37
+ rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
38
+ rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
39
+ rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
40
+ rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
41
+
42
+ BUNDLED WITH
43
+ 4.0.10
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2011 Allen A. Bargi <http://github.com/aziz>
2
+
3
+ Permission is hereby granted, free of charge, to any person ob-
4
+ taining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without restric-
6
+ tion, including without limitation the rights to use, copy, modi-
7
+ fy, merge, publish, distribute, sublicense, and/or sell copies of
8
+ the Software, and to permit persons to whom the Software is fur-
9
+ nished to do so, subject to 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
16
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONIN-
17
+ FRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,247 @@
1
+ # Jalali Date Library
2
+ A lightweight Ruby library for converting, formatting, and parsing Jalali (جلالی/Persian/Shamsi) dates.
3
+
4
+ Jalalidate provides simple APIs for:
5
+
6
+ * Gregorian → Jalali conversion
7
+ * Jalali → Gregorian conversion
8
+ * Jalali date formatting
9
+ * Parsing Persian date strings
10
+ * Working with Persian numerals and month names
11
+
12
+ ## Install
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'jalali-date'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle install
22
+
23
+ Or install it manually:
24
+
25
+ $ gem install jalali-date
26
+
27
+ ## Usage
28
+ Date conversion and class methods:
29
+ ```ruby
30
+ require 'jalali_date'
31
+
32
+ # Create a jalali date object:
33
+ j_date = JalaliDate.new(1402,02,25)
34
+ #=> <JalaliDate, :year => 1402, :month => 2, :day => 25 >
35
+
36
+ j_date = JalaliDate.new(Date.today)
37
+ #=> <JalaliDate, :year => 1402, :month => 2, :day => 25 >
38
+
39
+ # Initialize with hour, minute and second
40
+ j_date = JalaliDate.new(Time.now)
41
+ #=> <JalaliDate, :year => 1402, :month => 2, :day => 25, :hour => 6, :minute => 01, :second => 30 >
42
+
43
+ # Convert to gregorian date
44
+ g_date = j_date.to_gregorian
45
+ g_date = j_date.to_g
46
+ #=> Mon, 15 May 2023
47
+
48
+
49
+ # Get yesterday, today, or tomorrow in jalali
50
+ j_today = JalaliDate.yesterday
51
+ #=> <JalaliDate, :year => 1402, :month => 2, :day => 24 >
52
+ j_today = JalaliDate.today
53
+ #=> <JalaliDate, :year => 1402, :month => 2, :day => 25 >
54
+ j_tomorrow = JalaliDate.tomorrow
55
+ #=> <JalaliDate, :year => 1402, :month => 2, :day => 26 >
56
+
57
+ # Get year, month, and day
58
+ year = j_date.year #=> 1402
59
+ month = j_date.month #=> 02
60
+ day = j_date.day #=> 25
61
+
62
+ # Get gregorian year, month, and day
63
+ g_year = j_date.g_year #=> 2023
64
+ g_month = j_date.g_month #=> 5
65
+ g_day = j_date.g_day #=> 15
66
+
67
+ # Get day of the year
68
+ dy = j_date.yday #=> 51
69
+
70
+ # Get the next day
71
+ tomorrow = j_date.next
72
+ #=> <JalaliDate, :year => 1402, :month => 2, :day => 26 >
73
+
74
+ # Add and substract days
75
+ j_date + 6.days
76
+ #=> <JalaliDate, :year => 1402, :month => 2, :day => 31 >
77
+ j_date + 1.month
78
+ #=> <JalaliDate, :year => 1402, :month => 3, :day => 25 >
79
+ j_date + 2.years + 5.month + 12.days
80
+ #=> <JalaliDate, :year => 1404, :month => 8, :day => 5 >
81
+
82
+ # Shift the date with number of month
83
+ j_date >> 5
84
+ #=> <JalaliDate, :year => 1402, :month => 7, :day => 25 >
85
+ j_date << 5
86
+ #=> <JalaliDate, :year => 1401, :month => 9, :day => 25 >
87
+
88
+ # Compare two dates
89
+ j_date < j_date.next #=> true
90
+ j_date > j_date.next #=> false
91
+ j_date > j_date.previous #=> true
92
+ j_date <=> j_date.next #=> -1
93
+ j_date <=> j_date #=> 0
94
+ j_date <=> j_date.previous #=> 1
95
+
96
+ # Cycle through dates in different ways, namely, step, upto and downto
97
+ # every 2 days, including j_date, for the next 10 days
98
+ j_date.step( j_date + 10 , 2)
99
+
100
+ # every day, including j_date and the next 5 days
101
+ j_date.upto(j_date + 5)
102
+
103
+ # every day, including j_date and the previous 5 days
104
+ j_date.downto(j_date - 5)
105
+
106
+
107
+ # Get day object as array or hash
108
+ j_date.to_a #=> [1405, 2, 25]
109
+ j_date.to_hash #=> {year: 1405, month: 2, day: 25}
110
+
111
+
112
+ # Check for leap year
113
+ JalaliDate.leap? 1402
114
+ #=> false
115
+
116
+ # Check for validity of a jalali date
117
+ JalaliDate.valid?(1402,02,25)
118
+ #=> true
119
+
120
+ JalaliDate.valid?(1402,12,30)
121
+ #=> false
122
+ ```
123
+
124
+ ### Date formatting:
125
+
126
+ ```ruby
127
+ # Initialize with hour, minute and second
128
+ j_date = JalaliDate.new(Time.now)
129
+ #=> <JalaliDate, :year => 1402, :month => 2, :day => 25, :hour => 6, :minute => 01, :second => 30 >
130
+
131
+ j_date.strftime("%a %A %b %B %d %e %j %m %w %y %Y %% %x")
132
+ #=> "۲ش دوشنبه اردیبهشت Ordibehesht 25 25 56 2 1 02 1402 % 02/2/25"
133
+
134
+ j_date.strftime("%X")
135
+ #=> "06:01:30"
136
+
137
+ j_date.strftime("%H:%M - %Y/%n/%d")
138
+ #=> "06:01 - 1402/02/25"
139
+ ```
140
+
141
+ ## Format meanings:
142
+
143
+ - `[%a]` The abbreviated weekday name (۳ش)
144
+ - `[%A]` The full weekday name (یکشنبه)
145
+ - `[%b]` The month name (اردیبهشت)
146
+ - `[%B]` The month name in pinglish (Ordibehesht)
147
+ - `[%d]` Day of the month (01..31)
148
+ - `[%e]` Day of the month (1..31)
149
+ - `[%j]` Day of the year (1..366)
150
+ - `[%m]` Month of the year (1..12)
151
+ - `[%n]` Month of the year (01..12)
152
+ - `[%w]` Day of the week (Sunday is 0, 0..6)
153
+ - `[%x]` Preferred representation for the date alone, no time in format YY/M/D
154
+ - `[%y]` Year without a century (00..99)
155
+ - `[%Y]` Year with century
156
+ - `[%H]` Hour of the day, 24-hour clock (00..23)
157
+ - `[%I]` Hour of the day, 12-hour clock (01..12)
158
+ - `[%M]` Minute of the hour (00..59)
159
+ - `[%p]` Meridian indicator ("بعد از ظهر" or "قبل از ظهر")
160
+ - `[%P]` Meridian indicator ("ب.ظ" or "ق.ظ")
161
+ - `[%S]` Second of the minute (00..60)
162
+ - `[%X]` Preferred representation for the time alone, no date
163
+ - `[%Z]` Time zone name
164
+ - `[%%]` teral %'' character
165
+
166
+ ## Parsing Jalali Dates
167
+
168
+ The parser supports multiple common Persian date formats.
169
+
170
+ ### Numeric Formats
171
+ ```ruby
172
+ JalaliDate.parse('1402/02/25')
173
+ JalaliDate.parse('1402-02-25')
174
+ JalaliDate.parse('1402.02.25')
175
+ ```
176
+ ### Persian Month Names
177
+ ```ruby
178
+ JalaliDate.parse('25 اردیبهشت 1402')
179
+ JalaliDate.parse('اردیبهشت 25 1402')
180
+ ```
181
+
182
+ ### DateTime Parsing
183
+ ```ruby
184
+ JalaliDate.parse('1402/02/25 06:01')
185
+ JalaliDate.parse('1402/02/25 06:01:30')
186
+ JalaliDate.parse('25 اردیبهشت ۱۴۰۲ ساعت ۰۶:۰۱')
187
+ ```
188
+
189
+ ### Persian Digits
190
+
191
+ The parser automatically normalizes Persian and Arabic numerals:
192
+
193
+ ```ruby
194
+ JalaliDate.parse('۱۴۰۲/۰۲/۲۵')
195
+ JalaliDate.parse('١٤٠۲/٠٢/٢٥')
196
+ ```
197
+
198
+ ## Tests
199
+ Simply run `rspec` command in the source directory:
200
+
201
+ $ bundle exec rspec
202
+
203
+ ## History
204
+
205
+ #### 0.3.3 - 17.SEP.2013
206
+ * added %n formatter for numeric representation of a month, with leading zeros, courtesy of [Mohsen Alizadeh](https://github.com/m0h3n)
207
+
208
+ #### 0.3.2 - 8.APR.2013
209
+ * Making JalaliDate class thread safe, courtesy of [Jahangir Zinedine](https://github.com/jzinedine)
210
+
211
+ #### 0.3.1 - 26.APR.2011
212
+ * Added ruby 1.9 compatibility, courtesy of [Reza](https://github.com/ryco)
213
+
214
+ #### 0.3 - 6.JAN.2011
215
+ * JalaiDate could be initialized with Time and DateTime objects
216
+ * More options for strftime method %H,%M,%S,%X,%Z,%I,%p. read docs for more information
217
+ * Added jdate and jcal binaries to access jcal from the command-line
218
+ * Updated some documentations
219
+ * Now using bundler
220
+
221
+ #### 0.2 - 25.FEB.2010
222
+ * Renamed the gem from JalaliDate to jalalidate
223
+ * Added spec and a full test suite
224
+ * Updated gemspec file for rubygems.org
225
+ * Updated some documentations
226
+
227
+ #### 0.02 - 8.AUG.2008
228
+ * Added jalali to geregorian date convertor.
229
+ * Added JalaliDate class and ported Date class method to JalaliDate
230
+
231
+ #### 0.01 - 7.AUG.2008
232
+ * Planning the project
233
+
234
+
235
+ ## Note on Patches/Pull Requests
236
+
237
+ * Fork the project.
238
+ * Make your feature addition or bug fix.
239
+ * Add tests for it. This is important so I don't break it in a
240
+ future version unintentionally.
241
+ * Commit, do not mess with rakefile, version, or history.
242
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
243
+ * Send me a pull request. Bonus points for topic branches.
244
+
245
+ ## Copyright
246
+
247
+ Copyright (c) 2008-2011 Allen A. Bargi. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/TODO ADDED
@@ -0,0 +1,7 @@
1
+ =TODO
2
+ * add week number of the year %W and %U
3
+ * better jcal and jdate with param
4
+ * support afghan month names
5
+ * update read me / talk about the binaries
6
+ * ActiveSupport::CoreExtensions::Date
7
+ * ActionView::Helpers::DateHelper
data/bin/jcal ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'jalali_date'
4
+ require 'jalali_date/cli'
5
+
6
+ JalaliDate::Cli.jcal(*ARGV)
data/bin/jdate ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'jalali_date'
4
+ require 'jalali_date/cli'
5
+
6
+ JalaliDate::Cli.jdate(*ARGV)
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "jalali_date/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "jalali-date"
7
+ s.version = JalaliDate::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Allen A. Bargi", "Loqman Hakimi"]
10
+ s.email = %q{allen.bargi@gmail.com loqmanhakimi@gmail.com}
11
+
12
+ s.homepage = %q{http://github.com/loqman/jalalidate}
13
+ s.license = "MIT"
14
+ s.summary = %q{A library for working with Jalali Calendar (a.k.a Persian Calendar)}
15
+ s.required_ruby_version = '>= 3.0'
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+ s.extra_rdoc_files = [ "LICENSE", "README.md"]
21
+ s.rdoc_options = ["--charset=UTF-8"]
22
+
23
+ s.add_development_dependency 'bundler', '>= 1.16'
24
+ s.add_development_dependency 'rspec', '~> 3.0'
25
+ end
@@ -0,0 +1,36 @@
1
+ class JalaliDate
2
+ class Cli
3
+
4
+ # prints today's date in jalali calendar to STDOUT
5
+ #
6
+ def self.jdate(*args)
7
+ jdate = JalaliDate.new(Date.today)
8
+ puts jdate
9
+ end
10
+
11
+ # prints current month calendar in jalali calendar to STDOUT
12
+ #
13
+ def self.jcal(*args)
14
+ today = JalaliDate.new(Date.today)
15
+ jdate = JalaliDate.new(today.year,today.month,1)
16
+ # print month and year
17
+ puts jdate.strftime("%b %Y").center(26)
18
+ # print weekdays
19
+ puts JalaliDate::PERSIAN_ABBR_WEEKDAY_NAMES.reverse[1..6].join(" ") + " " + JalaliDate::PERSIAN_ABBR_WEEKDAY_NAMES.reverse[0] + " "
20
+ # print the month days
21
+ padding = true
22
+ JalaliDate::JDaysInMonth[jdate.month - 1].times do |index|
23
+ if padding
24
+ print " " * (jdate.jwday*4)
25
+ padding = false
26
+ end
27
+ print "%2d" % jdate.day + " "
28
+ print "\n" if jdate.jwday == 6
29
+ jdate = jdate.next
30
+ end
31
+
32
+ puts "\n"
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ class JalaliDate
2
+ VERSION = "0.3.7"
3
+ end
@@ -0,0 +1,372 @@
1
+ # encoding: utf-8
2
+ # :title:Jalali Date #
3
+ if RUBY_VERSION < '1.9'
4
+ require "jcode"
5
+ $KCODE = 'u'
6
+ end
7
+ require "date"
8
+ require "jalali_date_parser"
9
+
10
+ class JalaliDate
11
+
12
+ #:stopdoc:
13
+ GDaysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
14
+ JDaysInMonth = [31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29]
15
+ PERSIAN_MONTH_NAMES = [nil, "فروردین","اردیبهشت","خرداد","تیر","مرداد","شهریور","مهر","آبان","آذر","دی","بهمن","اسفند"]
16
+ PERSIAN_MONTH_NAMES_PINGLISH = [nil, "Farvardin", "Ordibehesht", "Khordad", "Tir", "Mordad", "Shahrivar", "Mehr", "Aban", "Azar", "Dey", "Bahman", "Esfand"]
17
+ PERSIAN_WEEKDAY_NAMES = ["یک‌شنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنج‌شنبه","جمعه","شنبه"]
18
+ PERSIAN_ABBR_WEEKDAY_NAMES = ["۱ش ","۲ش","۳ش","۴ش","۵ش","ج ","ش"]
19
+ PERSIAN_MERIDIAN_INDICATOR = ["قبل از ظهر","بعد از ظهر"]
20
+ PERSIAN_ABBR_MERIDIAN_INDICATOR = ["ق.ظ","ب.ظ"]
21
+ #:startdoc:
22
+
23
+ include Comparable
24
+
25
+ attr_accessor :year,:month,:day, :hour, :min, :sec
26
+ attr_reader :g_year, :g_month, :g_day
27
+
28
+ # Can be initialized in two ways:
29
+ # - First by feeding 3 arguments for Jalali Date, year,month and day.
30
+ # - The Second way to initializes is to pass a normal Ruby Date object, it'll be converted to jalali automatically.
31
+ #
32
+ # Example:
33
+ # jdate = JalaliDate.new(Date.today)
34
+ # other_jdate = JalaliDate.new(1388,9,17)
35
+ def initialize *args
36
+ if (args.size == 1) && (args.first.is_a?(Date))
37
+ year,month,day = gregorian_to_jalali(args.first.year, args.first.month, args.first.day)
38
+ elsif (args.size == 1) && (args.first.is_a?(Time) || args.first.is_a?(DateTime))
39
+ year,month,day = gregorian_to_jalali(args.first.year, args.first.month, args.first.day)
40
+ @hour = args.first.hour || 0
41
+ @min = args.first.min || 0
42
+ @sec = args.first.sec || 0
43
+ @zone = args.first.zone || "UTC"
44
+ @utc_offset = args.first.utc_offset || 0
45
+ else
46
+ year,month,day,hour,min,sec,zone,utc_offset = args
47
+ end
48
+
49
+ raise ArgumentError, "invalid arguments or invalid Jalali date" unless self.class.valid?(year,month,day)
50
+ @year = year
51
+ @month = month
52
+ @day = day
53
+ @hour ||= hour || 0
54
+ @min ||= min || 0
55
+ @sec ||= sec || 0
56
+ @zone ||= zone || "UTC"
57
+ @utc_offset ||= utc_offset || 0
58
+ @g_year, @g_month, @g_day = jalali_to_gregorian(year,month,day)
59
+ end
60
+
61
+ # Class Methods -----------------------------------------------------------
62
+ class << self
63
+ # Return a JalaliDate object representing today's date in calendar
64
+ def today
65
+ JalaliDate.new(Date.today)
66
+ end
67
+
68
+ # Return a JalaliDate object representing yesterday's date in calendar
69
+ def yesterday
70
+ JalaliDate.new(Date.today - 1)
71
+ end
72
+
73
+ # Return a JalaliDate object representing tomorrow's date in calendar
74
+ def tomorrow
75
+ JalaliDate.new(Date.today + 1)
76
+ end
77
+
78
+ # Return JalaliDate from a provided string
79
+ def parse(s)
80
+ date = JalaliDateParser.parse(s)
81
+ date[:jalali]
82
+ end
83
+
84
+ # Accpets a four digit number as the jalaliyear and returns true if that particular year
85
+ # is a leap year in jalali calendar otherwise it returns false.
86
+ def leap?(y)
87
+ [6,22,17,13,9,5,1,30].include?(y%33) ? true : false
88
+ end
89
+
90
+ # Accpets three numbers for year (4 digit), month and day in jalali calendar and checks if it's a
91
+ # valid date according to jalali calendar or not.
92
+ def valid?(y,m,d)
93
+ ( y.class == Integer && y > 0 &&
94
+ m.class == Integer && (1..12).include?(m) &&
95
+ d.class == Integer &&
96
+ (
97
+ ((1..JDaysInMonth[m-1]).include?(d)) || (d == 30 && m == 12 && leap?(y))
98
+ )
99
+ ) ? true : false
100
+ end
101
+ end
102
+
103
+ # Instance Methods --------------------------------------------------------
104
+
105
+ # Converts a JalaiDate object to Ruby Date object
106
+ def to_gregorian
107
+ Date.new(@g_year,@g_month,@g_day)
108
+ end
109
+ alias :to_g :to_gregorian
110
+
111
+ # Returns a string represtation of the JalaliDate object in format like this: y/m/d
112
+ def to_s
113
+ [@year,@month,@day].join("/")
114
+ end
115
+
116
+ # Returns a hash in a format like this: {:year => @year, :month => @month, :day => @day}
117
+ def to_hash
118
+ {:year => @year, :month => @month, :day => @day}
119
+ end
120
+
121
+ # Returns an array in a format like this: [y,m,d]
122
+ def to_a
123
+ [@year,@month,@day]
124
+ end
125
+
126
+ # Return internal object state as a programmer-readable string.
127
+ def inspect
128
+ "#<#{self.class}:#{self.object_id}, :year => #{@year}, :month => #{@month}, :day => #{@day} >"
129
+ end
130
+
131
+ # Adds n days to the current JalaliDate object
132
+ def +(days)
133
+ self.class.new( to_g + days )
134
+ end
135
+
136
+ # Subtracts n days from the current JalaliDate object
137
+ def -(days)
138
+ self.class.new( to_g - days )
139
+ end
140
+
141
+ # Return the next day for the current JalaliDate object
142
+ def next(n=1)
143
+ self + n
144
+ end
145
+ alias :succ :next
146
+
147
+ # Return the previous day for the current JalaliDate object
148
+ def previous(n=1)
149
+ self - n
150
+ end
151
+
152
+ # Compares two JalaliDate objects. acts like Date#<=>
153
+ def <=>(other)
154
+ to_g <=> other.to_g
155
+ end
156
+
157
+ # Move JalaliDate object forward by n months
158
+ def >>(months)
159
+ y, m = (@year * 12 + (@month - 1) + months).divmod(12)
160
+ m, = (m + 1) .divmod(1)
161
+ d = @day
162
+ d -= 1 until self.class.valid?(y, m, d)
163
+ self.class.new(y,m,d)
164
+ end
165
+
166
+ # Move JalaliDate object backward by n months
167
+ def <<(months)
168
+ self >> -months
169
+ end
170
+
171
+ # Step the current date forward +step+ days at a time (or backward, if step is negative) until we reach
172
+ # limit (inclusive), yielding the resultant date at each step.
173
+ #
174
+ # Example:
175
+ # jdate = JalaliDate.new(Date.today)
176
+ # jdate.step(Date.today+10, 2) do |jd|
177
+ # puts jd.to_s
178
+ # end
179
+ def step(limit, step=1)
180
+ da = self
181
+ op = %w(- <= >=)[step <=> 0]
182
+ while da.__send__(op, limit)
183
+ yield da
184
+ da += step
185
+ end
186
+ self
187
+ end
188
+
189
+ # Step forward one day at a time until we reach max (inclusive), yielding each date as we go.
190
+ #
191
+ # Example:
192
+ # jdate = JalaliDate.new(Date.today)
193
+ # days_string = ""
194
+ # jdate.upto(jdate+5) do |jd|
195
+ # days_string += jd.day.to_s
196
+ # end
197
+ def upto(max, &block)
198
+ step(max, +1, &block)
199
+ end
200
+
201
+ # Step backward one day at a time until we reach min (inclusive), yielding each date as we go.
202
+ # See #upto for the example.
203
+ def downto(min, &block)
204
+ step(min, -1, &block)
205
+ end
206
+
207
+ # Is this a leap year?
208
+ def leap?
209
+ self.class.leap?(@year)
210
+ end
211
+
212
+ # Get the week day of this date. Sunday is day-of-week 0; Saturday is day-of-week 6.
213
+ def wday
214
+ to_g.wday
215
+ end
216
+
217
+ # Get the jalali week day of this date. Saturday is day-of-week 0; Friday is day-of-week 6.
218
+ def jwday
219
+ (to_g.wday + 1) % 7
220
+ end
221
+
222
+ # Get the day-of-the-year of this date.
223
+ # Farvardin 1 is day-of-the-year 1
224
+ def yday
225
+ m = (@month-2 < 0) ? 0 : @month-2
226
+ (@month==1) ? @day : @day + JDaysInMonth[0..m].inject(0) {|sum, n| sum + n }
227
+ end
228
+
229
+ # Formats time according to the directives in the given format string. Any text not listed as a directive will be
230
+ # passed through to the output string.
231
+ #
232
+ # Format meanings:
233
+ #
234
+ # [%a] The abbreviated weekday name (۳ش)
235
+ # [%A] The full weekday name (یکشنبه)
236
+ # [%b] The month name (اردیبهشت)
237
+ # [%B] The month name in pinglish (Ordibehesht)
238
+ # [%d] Day of the month (01..31)
239
+ # [%e] Day of the month (1..31)
240
+ # [%j] Day of the year (1..366)
241
+ # [%m] Month of the year (1..12)
242
+ # [%n] Month of the year (01..12)
243
+ # [%w] Day of the week (Sunday is 0, 0..6)
244
+ # [%x] Preferred representation for the date alone, no time in format YY/M/D
245
+ # [%y] Year without a century (00..99)
246
+ # [%Y] Year with century
247
+ # [%H] Hour of the day, 24-hour clock (00..23)
248
+ # [%I] Hour of the day, 12-hour clock (01..12)
249
+ # [%M] Minute of the hour (00..59)
250
+ # [%p] Meridian indicator ("بعد از ظهر" or "قبل از ظهر")
251
+ # [%P] Meridian indicator ("ب.ظ" or "ق.ظ")
252
+ # [%S] Second of the minute (00..60)
253
+ # [%X] Preferred representation for the time alone, no date
254
+ # [%Z] Time zone name
255
+ # [%%] Literal %'' character
256
+ #
257
+ # Example:
258
+ # d = JalaliDate.today
259
+ # d.strftime("Printed on %Y/%m/%d") #=> "Printed on 87/5/26
260
+ def strftime(format_str = '%Y/%m/%d')
261
+ clean_fmt = format_str.gsub(/%{2}/, "SUBSTITUTION_MARKER").
262
+ gsub(/%a/, PERSIAN_ABBR_WEEKDAY_NAMES[wday]).
263
+ gsub(/%A/, PERSIAN_WEEKDAY_NAMES[wday]).
264
+ gsub(/%b/, PERSIAN_MONTH_NAMES[@month]).
265
+ gsub(/%B/, PERSIAN_MONTH_NAMES_PINGLISH[@month]).
266
+ gsub(/%d/, ("%02d" % @day).to_s).
267
+ gsub(/%e/, @day.to_s).
268
+ gsub(/%m/, @month.to_s).
269
+ gsub(/%n/, ("%02d" % @month).to_s).
270
+ gsub(/%Y/, @year.to_s).
271
+ gsub(/%y/, @year.to_s.slice(2,2)).
272
+ gsub(/%j/, yday.to_s).
273
+ gsub(/%H/, ("%02d" % @hour).to_s).
274
+ gsub(/%I/, ("%02d" % ((@hour>=12) ? @hour-12 : @hour)).to_s).
275
+ gsub(/%M/, ("%02d" % @min).to_s).
276
+ gsub(/%S/, ("%02d" % @sec).to_s).
277
+ gsub(/%p/, (@hour>=12 ? "بعد از ظهر" : "قبل از ظهر")).
278
+ gsub(/%P/, (@hour>=12 ? "ب.ظ" : "ق.ظ")).
279
+ gsub(/%w/, wday.to_s).
280
+ gsub(/%Z/, @zone).
281
+ gsub(/%X/, [("%02d" % @hour),("%02d" % @min),("%02d" % @sec)].join(":")).
282
+ gsub(/%x/, [@year.to_s.slice(2,2),@month,@day].join("/")).
283
+ gsub(/#{"SUBSTITUTION_MARKER"}/, '%')
284
+ end
285
+ alias :format :strftime
286
+
287
+ private #-------------------------------------------------------------------------
288
+
289
+ def gregorian_to_jalali(year, month, day) # :nodoc:
290
+ jj=0
291
+ gy = year - 1600
292
+ gm = month - 1
293
+ gd = day - 1
294
+ g_day_no = 365*gy + (gy+3)/4 - (gy+99)/100 + (gy+399)/400
295
+ gm.times { |i| g_day_no += GDaysInMonth[i] }
296
+ g_day_no += 1 if gm > 1 && ((gy%4 == 0 && gy%100 != 0) || (gy%400 == 0))
297
+ g_day_no += gd
298
+
299
+ j_day_no = g_day_no-79
300
+ j_np = j_day_no/12053
301
+ j_day_no %= 12053
302
+ jy = 979 + 33 * j_np + 4*(j_day_no/1461)
303
+ j_day_no %= 1461
304
+
305
+ if (j_day_no >= 366)
306
+ jy += (j_day_no - 1)/365
307
+ j_day_no = (j_day_no - 1) % 365
308
+ end
309
+
310
+ 11.times do |i|
311
+ if j_day_no >= JDaysInMonth[i]
312
+ j_day_no -= JDaysInMonth[i]
313
+ jj = i + 1
314
+ else
315
+ jj = i
316
+ break
317
+ end
318
+ end
319
+ jm = jj + 1
320
+ jd = j_day_no + 1
321
+
322
+ [jy, jm, jd]
323
+ end
324
+
325
+ def jalali_to_gregorian(year,month,day) # :nodoc:
326
+ gg=0
327
+ jy = year - 979
328
+ jm = month - 1
329
+ jd = day - 1
330
+ j_day_no = 365*jy + (jy/33)*8 + (jy % 33 + 3)/4
331
+ jm.times { |i| j_day_no += JDaysInMonth[i] }
332
+ j_day_no += jd
333
+
334
+ g_day_no = j_day_no + 79
335
+ gy = 1600 + 400*(g_day_no/146097)
336
+ g_day_no %= 146097
337
+
338
+ leap = true
339
+ if g_day_no >= 36525
340
+ g_day_no -= 1
341
+ gy += 100 * (g_day_no/36524)
342
+ g_day_no %= 36524
343
+ (g_day_no >= 365) ? g_day_no += 1 : leap = false
344
+ end
345
+
346
+ gy += 4 * (g_day_no/1461)
347
+ g_day_no %= 1461
348
+
349
+ if g_day_no >= 366
350
+ leap = false
351
+ g_day_no -= 1
352
+ gy += g_day_no/365
353
+ g_day_no %= 365
354
+ end
355
+
356
+ 11.times do |i|
357
+ leap_day = (i==1 && leap) ? 1 : 0
358
+ if g_day_no >= (GDaysInMonth[i] + leap_day )
359
+ g_day_no -= (GDaysInMonth[i] + leap_day )
360
+ gg = i + 1
361
+ else
362
+ gg = i
363
+ break
364
+ end
365
+ end
366
+ gm = gg + 1
367
+ gd = g_day_no + 1
368
+
369
+ [gy,gm,gd]
370
+ end
371
+
372
+ end
@@ -0,0 +1,182 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # Usage:
5
+ # JalaliDateParser.parse("1402/02/25")
6
+ # JalaliDateParser.parse("۱۴۰۲-۰۲-۲۵ ۰۶:۰۱")
7
+ # JalaliDateParser.parse("25 اردیبهشت 1402")
8
+ # JalaliDateParser.parse("25 اردیبهشت 1402 ساعت 6:01:30")
9
+ # JalaliDateParser.parse("1402.2.25")
10
+ # JalaliDateParser.parse("1402/02/25T06:01:30")
11
+ #
12
+ # Returns:
13
+ # {
14
+ # jalali: #<JalaliDate ...>,
15
+ # gregorian: #<DateTime ...>,
16
+ # components: {
17
+ # year: 1402,
18
+ # month: 2,
19
+ # day: 25,
20
+ # hour: 06,
21
+ # min: 01,
22
+ # sec: 30
23
+ # }
24
+ # }
25
+
26
+ require "date"
27
+ require "jalali_date"
28
+
29
+ module JalaliDateParser
30
+ PERSIAN_DIGITS = "۰۱۲۳۴۵۶۷۸۹"
31
+ ENGLISH_DIGITS = "0123456789"
32
+ ARABIC_DIGITS = "٠١٢٣٤٥٦٧٨٩"
33
+
34
+ MONTHS = {
35
+ "فروردین" => 1,
36
+ "اردیبهشت" => 2,
37
+ "خرداد" => 3,
38
+ "تیر" => 4,
39
+ "مرداد" => 5,
40
+ "شهریور" => 6,
41
+ "مهر" => 7,
42
+ "آبان" => 8,
43
+ "آذر" => 9,
44
+ "دی" => 10,
45
+ "بهمن" => 11,
46
+ "اسفند" => 12
47
+ }.freeze
48
+
49
+ COMMON_PATTERNS = [
50
+ # 1403/01/15
51
+ # 1403-01-15
52
+ # 1403.01.15
53
+ {
54
+ regex: /
55
+ (?<year>\d{4})
56
+ [\/\-.]
57
+ (?<month>\d{1,2})
58
+ [\/\-.]
59
+ (?<day>\d{1,2})
60
+ (?:[T\s]+(?<time>\d{1,2}:\d{1,2}(?::\d{1,2})?))?
61
+ /x
62
+ },
63
+
64
+ # 15/01/1403
65
+ # 15-01-1403
66
+ {
67
+ regex: /
68
+ (?<day>\d{1,2})
69
+ [\/\-.]
70
+ (?<month>\d{1,2})
71
+ [\/\-.]
72
+ (?<year>\d{4})
73
+ (?:[T\s]+(?<time>\d{1,2}:\d{1,2}(?::\d{1,2})?))?
74
+ /x
75
+ },
76
+
77
+ # 15 فروردین 1403
78
+ # فروردین 15 1403
79
+ {
80
+ regex: /
81
+ (?:
82
+ (?<day>\d{1,2})\s+
83
+ (?<month_name>[[:word:]\p{Arabic}]+)\s+
84
+ (?<year>\d{4})
85
+ |
86
+ (?<month_name2>[[:word:]\p{Arabic}]+)\s+
87
+ (?<day2>\d{1,2})\s+
88
+ (?<year2>\d{4})
89
+ )
90
+ (?:.*?(?<time>\d{1,2}:\d{1,2}(?::\d{1,2})?))?
91
+ /x
92
+ }
93
+ ].freeze
94
+
95
+ class ParseError < StandardError; end
96
+
97
+ module_function
98
+
99
+ def parse(input)
100
+ raise ParseError, "Empty input" if input.nil? || input.strip.empty?
101
+
102
+ str = normalize(input)
103
+
104
+ COMMON_PATTERNS.each do |pattern|
105
+ match = str.match(pattern[:regex])
106
+ next unless match
107
+
108
+ year = (match[:year] || match[:year2]).to_i
109
+ day = (match[:day] || match[:day2]).to_i
110
+
111
+ month =
112
+ if match.names.include?("month")
113
+ match[:month].to_i
114
+ else
115
+ MONTHS[match[:month_name] || match[:month_name2]]
116
+ end
117
+
118
+ hour, min, sec = extract_time(match[:time])
119
+
120
+ validate!(year, month, day, hour, min, sec)
121
+
122
+ jdate = JalaliDate.new(year, month, day, hour, min, sec)
123
+ gdate = jdate.to_gregorian.to_datetime
124
+
125
+ return {
126
+ jalali: jdate,
127
+ gregorian: gdate,
128
+ components: {
129
+ year: year,
130
+ month: month,
131
+ day: day,
132
+ hour: hour,
133
+ min: min,
134
+ sec: sec
135
+ }
136
+ }
137
+ end
138
+
139
+ raise ParseError, "Unsupported Jalali date format: #{input}"
140
+ end
141
+
142
+ def normalize(str)
143
+ s = str.dup
144
+
145
+ # Persian/Arabic digits → English
146
+ s.tr!(PERSIAN_DIGITS, ENGLISH_DIGITS)
147
+ s.tr!(ARABIC_DIGITS, ENGLISH_DIGITS)
148
+
149
+ # Normalize Arabic chars
150
+ s.gsub!("ي", "ی")
151
+ s.gsub!("ك", "ک")
152
+
153
+ # Remove extra words
154
+ s.gsub!(/ساعت|در|،/, " ")
155
+
156
+ # Normalize whitespace
157
+ s.gsub!(/\s+/, " ")
158
+
159
+ s.strip
160
+ end
161
+
162
+ def extract_time(time_str)
163
+ return [0, 0, 0] unless time_str
164
+
165
+ parts = time_str.split(":").map(&:to_i)
166
+
167
+ [
168
+ parts[0] || 0,
169
+ parts[1] || 0,
170
+ parts[2] || 0
171
+ ]
172
+ end
173
+
174
+ def validate!(year, month, day, hour, min, sec)
175
+ raise ParseError, "Invalid year" unless year > 0
176
+ raise ParseError, "Invalid month" unless month.between?(1, 12)
177
+ raise ParseError, "Invalid day" unless day.between?(1, 31)
178
+ raise ParseError, "Invalid hour" unless hour.between?(0, 23)
179
+ raise ParseError, "Invalid minute" unless min.between?(0, 59)
180
+ raise ParseError, "Invalid second" unless sec.between?(0, 59)
181
+ end
182
+ end
@@ -0,0 +1,158 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+
4
+ describe JalaliDate do
5
+
6
+ it "should initialize with valid year,month,date values" do
7
+ jdate = JalaliDate.new(1388,11,22)
8
+ jdate.should be_instance_of(JalaliDate)
9
+ end
10
+
11
+ it "should raise error for invalid year,month,date combination on initialize" do
12
+ lambda { JalaliDate.new(1388,14,22) }.should raise_error(ArgumentError) # invalid month
13
+ lambda { JalaliDate.new(1388,14,32) }.should raise_error(ArgumentError) # invalid day
14
+ lambda { JalaliDate.new(1388,14,"22") }.should raise_error(ArgumentError) # invalid type
15
+ lambda { JalaliDate.new(1388,14,22,11,0) }.should raise_error(ArgumentError) # invalid arguments
16
+ end
17
+
18
+ it "should initialize with a ruby date object" do
19
+ jdate = JalaliDate.new(Date.today)
20
+ jdate.should be_instance_of(JalaliDate)
21
+ end
22
+
23
+ it "should populate attr_accessors for jalali year, month and date and attr_reader for gregorian year,month and date" do
24
+ jdate = JalaliDate.new(1388,11,22)
25
+ jdate.year.should eql(1388)
26
+ jdate.month.should eql(11)
27
+ jdate.day.should eql(22)
28
+ jdate.g_year.should eql(2010)
29
+ jdate.g_month.should eql(2)
30
+ jdate.g_day.should eql(11)
31
+ end
32
+
33
+ it "should return today, yesterday, and tomorrow date according to jalali calendar" do
34
+ allow(Date).to receive(:today).and_return Date.new(2010,1,1)
35
+ JalaliDate.today.should === JalaliDate.new(1388,10,11)
36
+ JalaliDate.yesterday.should === JalaliDate.new(1388,10,10)
37
+ JalaliDate.tomorrow.should === JalaliDate.new(1388,10,12)
38
+ end
39
+
40
+ it "should distinguish invalid jalali dates" do
41
+ JalaliDate.valid?(1388,13,11).should be_falsey
42
+ JalaliDate.valid?(-1388,11,11).should be_falsey
43
+ JalaliDate.valid?(1388,1,45).should be_falsey
44
+ JalaliDate.valid?(1388,12,30).should be_falsey
45
+ JalaliDate.valid?(1387,12,30).should be_truthy
46
+ end
47
+
48
+ it "should distinguish leap years" do
49
+ JalaliDate.leap?(1387).should be_truthy
50
+ JalaliDate.leap?(1388).should be_falsey
51
+ end
52
+
53
+ it "should convert to gregorian date correctly" do
54
+ jdate = JalaliDate.new(1388,10,11)
55
+ jdate.to_g.should == Date.new(2010,1,1)
56
+ end
57
+
58
+ it "should convert to string, array and hash correctly" do
59
+ jdate = JalaliDate.new(1388,10,11)
60
+ jdate.to_s.should === "1388/10/11"
61
+ jdate.to_a.should === [1388,10,11]
62
+ jdate.to_hash.should === {:year => 1388, :month => 10, :day => 11}
63
+ end
64
+
65
+ it "should be able to add and substract days from the currect jalai date object" do
66
+ jdate = JalaliDate.new(1388,10,11)
67
+ five_days_later = jdate + 5
68
+ twenty_days_ago = jdate - 20
69
+ five_days_later.should === JalaliDate.new(1388,10,16)
70
+ twenty_days_ago.should === JalaliDate.new(1388,9,21)
71
+ end
72
+
73
+ it "should be able to compare two jalali dates" do
74
+ jdate = JalaliDate.new(1388,10,11)
75
+ next_month_jdate = JalaliDate.new(1388,11,11)
76
+ next_month_jdate.<=>(jdate).should === 1
77
+ jdate.<=>(next_month_jdate).should === -1
78
+ jdate.<=>(jdate).should == 0
79
+ end
80
+
81
+ it "should now its next and previous dates" do
82
+ jdate = JalaliDate.new(1388,10,11)
83
+ jdate.next.should === JalaliDate.new(1388,10,12)
84
+ jdate.previous.should === JalaliDate.new(1388,10,10)
85
+ end
86
+
87
+ it "should be able to move the month forward and backward" do
88
+ jdate = JalaliDate.new(1388,10,11)
89
+ five_month_later = jdate >> 5
90
+ five_month_ago = jdate << 5
91
+ five_month_later.should === JalaliDate.new(1389,3,11)
92
+ five_month_ago.should === JalaliDate.new(1388,5,11)
93
+ end
94
+
95
+ it "should be able to cycle through dates in different ways, namely, step, upto and downto" do
96
+ jdate = JalaliDate.new(1388,10,10)
97
+
98
+ days_string = ""
99
+ jdate.step( jdate + 10 , 2) do |jd|
100
+ days_string += jd.day.to_s
101
+ end
102
+ days_string.should === "101214161820"
103
+
104
+ days_string = ""
105
+ jdate.upto(jdate+5) do |jd|
106
+ days_string += jd.day.to_s
107
+ end
108
+ days_string.should === "101112131415"
109
+
110
+ days_string = ""
111
+ jdate.downto(jdate-5) do |jd|
112
+ days_string += jd.day.to_s
113
+ end
114
+ days_string.should == "1098765"
115
+ end
116
+
117
+ it "should return a correct year day based on Jalali Calendar" do
118
+ JalaliDate.new(1388,1,1).yday.should === 1
119
+ JalaliDate.new(1388,12,29).yday.should === 365
120
+ JalaliDate.new(1387,12,30).yday.should === 366
121
+ JalaliDate.new(1388,9,17).yday.should === 263
122
+ end
123
+
124
+ it "should be able to print jalali date in different formats" do
125
+ JalaliDate.new(1388,1,7).strftime("%a %A %b %B %d %e %j %m %w %y %Y %% %x").should == "ج جمعه فروردین Farvardin 07 7 7 1 5 88 1388 % 88/1/7"
126
+ end
127
+
128
+ it "should be intialize with a time object" do
129
+ time = Time.now
130
+ JalaliDate.new(time).hour.should == time.hour
131
+ end
132
+
133
+ it "should be able for format %H %I %M %p %S %X %Z correctly if initiallized with time" do
134
+ JalaliDate.new(1388,2,15,5,50,10).strftime("%H").should === "05"
135
+ JalaliDate.new(1388,2,15,18,50,10).strftime("%H %I").should === "18 06"
136
+ JalaliDate.new(1388,2,15,12,50,10).strftime("%H %I").should === "12 00"
137
+ JalaliDate.new(1388,2,15,12,50,10).strftime("%H %I %M %S").should === "12 00 50 10"
138
+ JalaliDate.new(1388,2,15,5,50,10).strftime("%p").should === "قبل از ظهر"
139
+ JalaliDate.new(1388,2,15,15,50,10).strftime("%p").should === "بعد از ظهر"
140
+ JalaliDate.new(1388,2,15,15,50,10).strftime("%X").should === "15:50:10"
141
+ JalaliDate.new(1388,2,15,15,50,10).strftime("%X").should === "15:50:10"
142
+ JalaliDate.new(1388,2,15,15,50,10,"CET",3600).strftime("%Z").should === "CET"
143
+ JalaliDate.new(1388,2,2,5,50,10).strftime("%n").should === "02"
144
+ JalaliDate.new(1388,2,2,5,50,10).strftime("%m").should === "2"
145
+ time = Time.now
146
+ JalaliDate.new(time).strftime("%Z").should == time.zone
147
+ end
148
+
149
+ it "should be able to parse different formats of jalali dates" do
150
+ JalaliDate.parse("1402/02/25").should == JalaliDate.new(1402,2,25)
151
+ JalaliDate.parse("۱۴۰۲-۰۲-۲۵ ۰۶:۰۱").should == JalaliDate.new(1402,2,25)
152
+ JalaliDate.parse("25 اردیبهشت 1402").should == JalaliDate.new(1402,2,25)
153
+ JalaliDate.parse("25 اردیبهشت 1402 ساعت 6:01:30").should == JalaliDate.new(1402,2,25)
154
+ JalaliDate.parse("1402.2.25").should == JalaliDate.new(1402,2,25)
155
+ JalaliDate.parse("1402/02/25T06:01:30").should == JalaliDate.new(1402,2,25)
156
+ end
157
+
158
+ end
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'jalali_date'
5
+ require 'rspec'
6
+
7
+ RSpec.configure do |config|
8
+ config.expect_with(:rspec) { |c| c.syntax = :should }
9
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jalali-date
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.7
5
+ platform: ruby
6
+ authors:
7
+ - Allen A. Bargi
8
+ - Loqman Hakimi
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ email: allen.bargi@gmail.com loqmanhakimi@gmail.com
42
+ executables:
43
+ - jcal
44
+ - jdate
45
+ extensions: []
46
+ extra_rdoc_files:
47
+ - LICENSE
48
+ - README.md
49
+ files:
50
+ - ".gitignore"
51
+ - ".travis.yml"
52
+ - Gemfile
53
+ - Gemfile.lock
54
+ - LICENSE
55
+ - README.md
56
+ - Rakefile
57
+ - TODO
58
+ - bin/jcal
59
+ - bin/jdate
60
+ - jalalidate.gemspec
61
+ - lib/jalali_date.rb
62
+ - lib/jalali_date/cli.rb
63
+ - lib/jalali_date/version.rb
64
+ - lib/jalali_date_parser.rb
65
+ - spec/jalali_date_spec.rb
66
+ - spec/spec_helper.rb
67
+ homepage: http://github.com/loqman/jalalidate
68
+ licenses:
69
+ - MIT
70
+ metadata: {}
71
+ rdoc_options:
72
+ - "--charset=UTF-8"
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '3.0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubygems_version: 4.0.10
87
+ specification_version: 4
88
+ summary: A library for working with Jalali Calendar (a.k.a Persian Calendar)
89
+ test_files: []