Class: JalaliDate

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/jalalidate.rb

Constant Summary collapse

GDaysInMonth =

:stopdoc:

[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
JDaysInMonth =
[31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29]
PERSIAN_MONTH_NAMES =
[nil, "فروردین","اردیبهشت","خرداد","تیر","مرداد","شهریور","مهر","آبان","آذر","دی","بهمن","اسفند"]
PERSIAN_MONTH_NAMES_PINGLISH =
[nil, "Farvardin", "Ordibehesht", "Khordad", "Tir", "Mordad", "Shahrivar", "Mehr", "Aban", "Azar", "Dey", "Bahman", "Esfand"]
PERSIAN_WEEKDAY_NAMES =
["یک‌شنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنج‌شنبه","جمعه","شنبه"]
PERSIAN_ABBR_WEEKDAY_NAMES =
["۱ش ","۲ش","۳ش","۴ش","۵ش","ج ","ش"]
PERSIAN_MERIDIAN_INDICATOR =
["قبل از ظهر","بعد از ظهر"]
PERSIAN_ABBR_MERIDIAN_INDICATOR =
["ق.ظ","ب.ظ"]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ JalaliDate

Can be initialized in two ways:

  • First by feeding 3 arguments for Jalali Date, year,month and day.

  • The Second way to initializes is to pass a normal Ruby Date object, it’ll be converted to jalali automatically.

Example:

jdate = JalaliDate.new(Date.today)
other_jdate = JalaliDate.new(1388,9,17)

Raises:

  • (ArgumentError)


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/jalalidate.rb', line 34

def initialize *args
  if (args.size == 1) && (args.first.is_a?(Date))
    year,month,day = gregorian_to_jalali(args.first.year, args.first.month, args.first.day)
  elsif (args.size == 1) && (args.first.is_a?(Time) || args.first.is_a?(DateTime))
    year,month,day = gregorian_to_jalali(args.first.year, args.first.month, args.first.day)
    @hour = args.first.hour || 0
    @min  = args.first.min  || 0
    @sec  = args.first.sec  || 0
    @zone = args.first.zone || "UTC"
    @utc_offset = args.first.utc_offset  || 0
  else
    year,month,day,hour,min,sec,zone,utc_offset = args
  end

  raise ArgumentError, "invalid arguments or invalid Jalali date" unless self.class.valid?(year,month,day)
  @year  = year
  @month = month
  @day   = day
  @hour ||=  hour || 0
  @min  ||=  min  || 0
  @sec  ||=  sec  || 0
  @zone ||=  zone || "UTC"
  @utc_offset ||= utc_offset || 0
  @g_year, @g_month, @g_day = jalali_to_gregorian(year,month,day)
end

Instance Attribute Details

#dayObject

Returns the value of attribute day.



24
25
26
# File 'lib/jalalidate.rb', line 24

def day
  @day
end

#g_dayObject (readonly)

Returns the value of attribute g_day.



25
26
27
# File 'lib/jalalidate.rb', line 25

def g_day
  @g_day
end

#g_monthObject (readonly)

Returns the value of attribute g_month.



25
26
27
# File 'lib/jalalidate.rb', line 25

def g_month
  @g_month
end

#g_yearObject (readonly)

Returns the value of attribute g_year.



25
26
27
# File 'lib/jalalidate.rb', line 25

def g_year
  @g_year
end

#hourObject

Returns the value of attribute hour.



24
25
26
# File 'lib/jalalidate.rb', line 24

def hour
  @hour
end

#minObject

Returns the value of attribute min.



24
25
26
# File 'lib/jalalidate.rb', line 24

def min
  @min
end

#monthObject

Returns the value of attribute month.



24
25
26
# File 'lib/jalalidate.rb', line 24

def month
  @month
end

#secObject

Returns the value of attribute sec.



24
25
26
# File 'lib/jalalidate.rb', line 24

def sec
  @sec
end

#yearObject

Returns the value of attribute year.



24
25
26
# File 'lib/jalalidate.rb', line 24

def year
  @year
end

Class Method Details

.leap?(y) ⇒ Boolean

Accpets a four digit number as the jalaliyear and returns true if that particular year is a leap year in jalali calendar otherwise it returns false.

Returns:

  • (Boolean)


79
80
81
# File 'lib/jalalidate.rb', line 79

def leap?(y)
  [6,22,17,13,9,5,1,30].include?(y%33) ? true : false
end

.todayObject

Return a JalaliDate object representing today’s date in calendar



63
64
65
# File 'lib/jalalidate.rb', line 63

def today
  JalaliDate.new(Date.today)
end

.tomorrowObject

Return a JalaliDate object representing tomorrow’s date in calendar



73
74
75
# File 'lib/jalalidate.rb', line 73

def tomorrow
  JalaliDate.new(Date.today + 1)
end

.valid?(y, m, d) ⇒ Boolean

Accpets three numbers for year (4 digit), month and day in jalali calendar and checks if it’s a valid date according to jalali calendar or not.

Returns:

  • (Boolean)


85
86
87
88
89
90
91
92
93
# File 'lib/jalalidate.rb', line 85

def valid?(y,m,d)
  ( y.class == Integer && y > 0 &&
    m.class == Integer && (1..12).include?(m) &&
    d.class == Integer &&
    (
      ((1..JDaysInMonth[m-1]).include?(d)) || (d == 30 && m == 12 && leap?(y))
    )
  ) ? true : false
end

.yesterdayObject

Return a JalaliDate object representing yesterday’s date in calendar



68
69
70
# File 'lib/jalalidate.rb', line 68

def yesterday
  JalaliDate.new(Date.today - 1)
end

Instance Method Details

#+(days) ⇒ Object

Adds n days to the current JalaliDate object



125
126
127
# File 'lib/jalalidate.rb', line 125

def +(days)
  self.class.new( to_g + days )
end

#-(days) ⇒ Object

Subtracts n days from the current JalaliDate object



130
131
132
# File 'lib/jalalidate.rb', line 130

def -(days)
  self.class.new( to_g - days )
end

#<<(months) ⇒ Object

Move JalaliDate object backward by n months



160
161
162
# File 'lib/jalalidate.rb', line 160

def <<(months)
  self >> -months
end

#<=>(other) ⇒ Object

Compares two JalaliDate objects. acts like Date#<=>



146
147
148
# File 'lib/jalalidate.rb', line 146

def <=>(other)
  to_g <=> other.to_g
end

#>>(months) ⇒ Object

Move JalaliDate object forward by n months



151
152
153
154
155
156
157
# File 'lib/jalalidate.rb', line 151

def >>(months)
  y, m = (@year * 12 + (@month - 1) + months).divmod(12)
  m,   = (m + 1)                    .divmod(1)
  d = @day
  d -= 1 until self.class.valid?(y, m, d)
  self.class.new(y,m,d)
end

#downto(min, &block) ⇒ Object

Step backward one day at a time until we reach min (inclusive), yielding each date as we go. See #upto for the example.



196
197
198
# File 'lib/jalalidate.rb', line 196

def downto(min, &block)
  step(min, -1, &block)
end

#inspectObject

Return internal object state as a programmer-readable string.



120
121
122
# File 'lib/jalalidate.rb', line 120

def inspect
  "#<#{self.class}:#{self.object_id}, :year => #{@year}, :month => #{@month}, :day => #{@day} >"
end

#jwdayObject

Get the jalali week day of this date. Saturday is day-of-week 0; Friday is day-of-week 6.



211
212
213
# File 'lib/jalalidate.rb', line 211

def jwday
  (to_g.wday + 1) % 7
end

#leap?Boolean

Is this a leap year?

Returns:

  • (Boolean)


201
202
203
# File 'lib/jalalidate.rb', line 201

def leap?
  self.class.leap?(@year)
end

#next(n = 1) ⇒ Object Also known as: succ

Return the next day for the current JalaliDate object



135
136
137
# File 'lib/jalalidate.rb', line 135

def next(n=1)
  self + n
end

#previous(n = 1) ⇒ Object

Return the previous day for the current JalaliDate object



141
142
143
# File 'lib/jalalidate.rb', line 141

def previous(n=1)
  self - n
end

#step(limit, step = 1) ⇒ Object

Step the current date forward step days at a time (or backward, if step is negative) until we reach limit (inclusive), yielding the resultant date at each step.

Example:

jdate = JalaliDate.new(Date.today)
jdate.step(Date.today+10, 2) do |jd|
  puts jd.to_s
end


172
173
174
175
176
177
178
179
180
# File 'lib/jalalidate.rb', line 172

def step(limit, step=1)
  da = self
  op = %w(- <= >=)[step <=> 0]
  while da.__send__(op, limit)
    yield da
    da += step
  end
  self
end

#strftime(format_str = '%Y/%m/%d') ⇒ Object Also known as: format

Formats time according to the directives in the given format string. Any text not listed as a directive will be passed through to the output string.

Format meanings:

%a

The abbreviated weekday name (۳ش)

%A

The full weekday name (یکشنبه)

%b

The month name (اردیبهشت)

%B

The month name in pinglish (Ordibehesht)

%d

Day of the month (01..31)

%e

Day of the month (1..31)

%j

Day of the year (1..366)

%m

Month of the year (1..12)

%n

Month of the year (01..12)

%w

Day of the week (Sunday is 0, 0..6)

%x

Preferred representation for the date alone, no time in format YY/M/D

%y

Year without a century (00..99)

%Y

Year with century

%H

Hour of the day, 24-hour clock (00..23)

%I

Hour of the day, 12-hour clock (01..12)

%M

Minute of the hour (00..59)

%p

Meridian indicator (“بعد از ظهر” or “قبل از ظهر”)

%S

Second of the minute (00..60)

%X

Preferred representation for the time alone, no date

%Z

Time zone name

%%

Literal %” character

Example:

d = JalaliDate.today
d.strftime("Printed on %Y/%m/%d")   #=> "Printed on 87/5/26


252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/jalalidate.rb', line 252

def strftime(format_str = '%Y/%m/%d')
  clean_fmt = format_str.gsub(/%{2}/, "SUBSTITUTION_MARKER").
    gsub(/%a/, PERSIAN_ABBR_WEEKDAY_NAMES[wday]).
    gsub(/%A/, PERSIAN_WEEKDAY_NAMES[wday]).
    gsub(/%b/, PERSIAN_MONTH_NAMES[@month]).
    gsub(/%B/, PERSIAN_MONTH_NAMES_PINGLISH[@month]).
    gsub(/%d/, ("%02d" % @day).to_s).
    gsub(/%e/, @day.to_s).
    gsub(/%m/, @month.to_s).
   gsub(/%n/, ("%02d" % @month).to_s).
    gsub(/%Y/, @year.to_s).
    gsub(/%y/, @year.to_s.slice(2,2)).
    gsub(/%j/, yday.to_s).
    gsub(/%H/, ("%02d" % @hour).to_s).
    gsub(/%I/, ("%02d" % ((@hour>=12) ? @hour-12 : @hour)).to_s).
    gsub(/%M/, ("%02d" % @min).to_s).
    gsub(/%S/, ("%02d" % @sec).to_s).
    gsub(/%p/, (@hour>=12 ? "بعد از ظهر" : "قبل از ظهر")).
    gsub(/%w/, wday.to_s).
    gsub(/%Z/, @zone).
    gsub(/%X/, [("%02d" % @hour),("%02d" % @min),("%02d" % @sec)].join(":")).
    gsub(/%x/, [@year.to_s.slice(2,2),@month,@day].join("/")).
    gsub(/#{"SUBSTITUTION_MARKER"}/, '%')
end

#to_aObject

Returns an array in a format like this: [y,m,d]



115
116
117
# File 'lib/jalalidate.rb', line 115

def to_a
  [@year,@month,@day]
end

#to_gregorianObject Also known as: to_g

Converts a JalaiDate object to Ruby Date object



99
100
101
# File 'lib/jalalidate.rb', line 99

def to_gregorian
  Date.new(@g_year,@g_month,@g_day)
end

#to_hashObject

Returns a hash in a format like this: => @year, :month => @month, :day => @day



110
111
112
# File 'lib/jalalidate.rb', line 110

def to_hash
  {:year => @year, :month => @month, :day => @day}
end

#to_sObject

Returns a string represtation of the JalaliDate object in format like this: y/m/d



105
106
107
# File 'lib/jalalidate.rb', line 105

def to_s
  [@year,@month,@day].join("/")
end

#upto(max, &block) ⇒ Object

Step forward one day at a time until we reach max (inclusive), yielding each date as we go.

Example:

jdate = JalaliDate.new(Date.today)
days_string = ""
jdate.upto(jdate+5) do |jd|
  days_string += jd.day.to_s
end


190
191
192
# File 'lib/jalalidate.rb', line 190

def upto(max, &block)
  step(max, +1, &block)
end

#wdayObject

Get the week day of this date. Sunday is day-of-week 0; Saturday is day-of-week 6.



206
207
208
# File 'lib/jalalidate.rb', line 206

def wday
  to_g.wday
end

#ydayObject

Get the day-of-the-year of this date. Farvardin 1 is day-of-the-year 1



217
218
219
220
# File 'lib/jalalidate.rb', line 217

def yday
  m = (@month-2 < 0) ? 0 : @month-2
  (@month==1) ? @day : @day + JDaysInMonth[0..m].inject(0) {|sum, n| sum + n }
end