japanese_calendar 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -40,6 +40,16 @@ Time.new(1912, 7, 30).era_name(:romaji) # => "Taisho"
40
40
  Time.new(1873, 1, 1).era_name(:romaji) # => "Meiji"
41
41
  ```
42
42
 
43
+ The following examples show how to check the Japanese era:
44
+
45
+ ```
46
+ Time.new(2019, 5, 1).reiwa? # => true
47
+ Time.new(1989, 1, 8).heisei? # => true
48
+ Time.new(1926, 12, 25).showa? # => true
49
+ Time.new(1912, 7, 30).taisho? # => true
50
+ Time.new(1873, 1, 1).meiji? # => true
51
+ ```
52
+
43
53
  You can convert to a Japanese year with the `era_year` method:
44
54
 
45
55
  ```
@@ -57,6 +67,7 @@ time = Time.new(2019, 5, 1)
57
67
 
58
68
  # Japanese era
59
69
  time.strftime("%JN") # => "令和"
70
+ time.strftime("%Jn") # => "令"
60
71
  time.strftime("%JR") # => "Reiwa"
61
72
  time.strftime("%^JR") # => "REIWA"
62
73
  time.strftime("%Jr") # => "R"
@@ -4,7 +4,7 @@ require 'date'
4
4
  require 'japanese_calendar/era'
5
5
  require 'japanese_calendar/weekday'
6
6
 
7
- class Date
7
+ class Date #:nodoc:
8
8
  prepend JapaneseCalendar::Era
9
9
  prepend JapaneseCalendar::Weekday
10
10
  end
@@ -4,7 +4,7 @@ require 'date'
4
4
  require 'japanese_calendar/era'
5
5
  require 'japanese_calendar/weekday'
6
6
 
7
- class DateTime
7
+ class DateTime #:nodoc:
8
8
  prepend JapaneseCalendar::Era
9
9
  prepend JapaneseCalendar::Weekday
10
10
  end
@@ -3,7 +3,7 @@
3
3
  require 'japanese_calendar/era'
4
4
  require 'japanese_calendar/weekday'
5
5
 
6
- class Time
6
+ class Time #:nodoc:
7
7
  prepend JapaneseCalendar::Era
8
8
  prepend JapaneseCalendar::Weekday
9
9
  end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'japanese_calendar/deprecation/reporting'
4
+
5
+ module JapaneseCalendar
6
+ module Deprecation #:nodoc: all
7
+ ERA_DIRECTIVES = {
8
+ '%K' => '%JN',
9
+ '%O' => '%JR',
10
+ '%^O' => '%^JR',
11
+ '%o' => '%Jr',
12
+ '%J' => '%Jy',
13
+ '%-J' => '%-Jy',
14
+ '%_J' => '%_Jy'
15
+ }.freeze
16
+
17
+ ERA_PATTERN = Regexp.union(ERA_DIRECTIVES.keys)
18
+
19
+ private_constant :ERA_DIRECTIVES, :ERA_PATTERN
20
+
21
+ # Prepend wrapper for Era module
22
+ module EraWrapper
23
+ include JapaneseCalendar::Deprecation::Reporting
24
+
25
+ def strftime(format)
26
+ string = super(format)
27
+ deprecations = collect_era_deprecations(string)
28
+ deprecations.each { |deprecation| deprecate_directive(*deprecation) }
29
+ string.gsub(deprecated_era_pattern, deprecated_era_conversion)
30
+ end
31
+
32
+ private
33
+
34
+ def collect_era_deprecations(format)
35
+ deprecated_directives = format.scan(ERA_PATTERN).uniq
36
+ ERA_DIRECTIVES.select do |directive, _|
37
+ deprecated_directives.include?(directive)
38
+ end
39
+ end
40
+
41
+ def deprecated_era_conversion
42
+ {
43
+ '%K' => era_kanji_name,
44
+ '%O' => era_romaji_name,
45
+ '%^O' => era_romaji_uppercased_name,
46
+ '%o' => era_romaji_abbreviation,
47
+ '%J' => era_year_zero_padded_string,
48
+ '%-J' => era_year_string,
49
+ '%_J' => era_year_blank_padded_string
50
+ }
51
+ end
52
+
53
+ def deprecated_era_pattern
54
+ Regexp.union(deprecated_era_conversion.keys)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JapaneseCalendar
4
+ module Deprecation
5
+ module Reporting #:nodoc:
6
+ private
7
+
8
+ def deprecate_directive(directive, replacement)
9
+ deprecate(directive, "Please use #{replacement} instead.")
10
+ end
11
+
12
+ def deprecate(directive, message)
13
+ warn "#{directive} is deprecated. #{message}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'japanese_calendar/deprecation/reporting'
4
+
5
+ module JapaneseCalendar
6
+ module Deprecation #:nodoc: all
7
+ WEEKDAY_DIRECTIVES = {
8
+ '%Q' => '%JA',
9
+ '%q' => '%Ja'
10
+ }.freeze
11
+
12
+ WEEKDAY_PATTERN = Regexp.union(WEEKDAY_DIRECTIVES.keys)
13
+
14
+ private_constant :WEEKDAY_DIRECTIVES, :WEEKDAY_PATTERN
15
+
16
+ # Prepend wrapper for Weekday module
17
+ module WeekdayWrapper
18
+ include JapaneseCalendar::Deprecation::Reporting
19
+
20
+ def strftime(format)
21
+ string = super(format)
22
+ deprecations = collect_weekday_deprecations(string)
23
+ deprecations.each { |deprecation| deprecate_directive(*deprecation) }
24
+ string.gsub(deprecated_weekday_pattern, deprecated_weekday_conversion)
25
+ end
26
+
27
+ private
28
+
29
+ def collect_weekday_deprecations(format)
30
+ deprecated_directives = format.scan(WEEKDAY_PATTERN).uniq
31
+ WEEKDAY_DIRECTIVES.select do |directive, _|
32
+ deprecated_directives.include?(directive)
33
+ end
34
+ end
35
+
36
+ def deprecated_weekday_conversion
37
+ {
38
+ '%Q' => weekday_name,
39
+ '%q' => weekday_abbreviation
40
+ }
41
+ end
42
+
43
+ def deprecated_weekday_pattern
44
+ Regexp.union(deprecated_weekday_conversion.keys)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,30 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'japanese_calendar/era/deprecator'
3
+ require 'japanese_calendar/deprecation/era_wrapper'
4
+ require 'japanese_calendar/era/calculations'
5
+ require 'japanese_calendar/era/reflection'
4
6
 
5
7
  module JapaneseCalendar
8
+ # Era extensions to <tt>Date</tt>, <tt>DateTime</tt> and
9
+ # <tt>Time</tt>.
6
10
  module Era
7
- prepend Era::Deprecator
11
+ include Era::Calculations
12
+ include Era::Reflection
13
+ prepend Deprecation::EraWrapper
8
14
 
9
- Period = Struct.new(:beginning_of_period, :kanji_name, :romaji_name)
10
-
11
- MEIJI_6 = Date.new(1873, 1, 1)
12
-
13
- PERIODS = [
14
- Period.new(Date.new(2019, 5, 1), '令和', 'Reiwa').freeze,
15
- Period.new(Date.new(1989, 1, 8), '平成', 'Heisei').freeze,
16
- Period.new(Date.new(1926, 12, 25), '昭和', 'Showa').freeze,
17
- Period.new(Date.new(1912, 7, 30), '大正', 'Taisho').freeze,
18
- Period.new(Date.new(1868, 1, 25), '明治', 'Meiji').freeze
19
- ].freeze
20
-
21
- private_constant :Period, :MEIJI_6, :PERIODS
22
-
23
- # Formats time according to the directives in the given format string.
15
+ # Formats the year of the Japanese era according to the directives in the
16
+ # given format string.
17
+ #
18
+ # Format directives:
19
+ # %JN - The full Japanese era name in Kanji ("令和")
20
+ # %Jn - The abbreviated Japanese era name in Kanji ("令")
21
+ # %JR - The full Japanese era name in Romaji ("Reiwa")
22
+ # %^JR uppercased ("REIWA")
23
+ # %Jr - The abbreviated Japanese era name in Romaji ("R")
24
+ # %Jy - year of the Japanese era, zero-padded (01)
25
+ # %_Jy blank-padded ( 1)
26
+ # %-Jy no-padded (1)
24
27
  #
28
+ # Examples:
25
29
  # date_of_birth = Time.new(1978, 7, 19)
26
30
  #
27
31
  # date_of_birth.strftime("%JN") # => "昭和"
32
+ # date_of_birth.strftime("%Jn") # => "昭"
28
33
  # date_of_birth.strftime("%JR") # => "Showa"
29
34
  # date_of_birth.strftime("%^JR") # => "SHOWA"
30
35
  # date_of_birth.strftime("%Jr") # => "S"
@@ -36,115 +41,29 @@ module JapaneseCalendar
36
41
  #
37
42
  # Time.new(1872, 12, 31).strftime("%JN%-Jy年") # => RuntimeError
38
43
  def strftime(format)
39
- string = format.gsub(era_pattern, era_conversion)
40
- super(string)
41
- end
42
-
43
- # Returns the Japanese era name (nengo) since 1 January 1873 (Meiji 6).
44
- #
45
- # reiwa = Time.new(2019, 5, 1) # => 2019-05-01 00:00:00 +0900
46
- # reiwa.era_name # => "令和"
47
- # reiwa.era_name(:romaji) # => "Reiwa"
48
- #
49
- # heisei = Time.new(1989, 1, 8) # => 1989-01-08 00:00:00 +0900
50
- # heisei.era_name # => "平成"
51
- # heisei.era_name(:romaji) # => "Heisei"
52
- #
53
- # showa = Time.new(1926, 12, 25) # => 1926-12-25 00:00:00 +0900
54
- # showa.era_name # => "昭和"
55
- # showa.era_name(:romaji) # => "Showa"
56
- #
57
- # taisho = Time.new(1912, 7, 30) # => 1912-07-30 00:00:00 +0900
58
- # taisho.era_name # => "大正"
59
- # taisho.era_name(:romaji) # => "Taisho"
60
- #
61
- # meiji = Time.new(1873, 1, 1) # => 1873-01-01 00:00:00 +0900
62
- # meiji.era_name # => "明治"
63
- # meiji.era_name(:romaji) # => "Meiji"
64
- #
65
- # Raises an error when the Japanese era name cannot be found.
66
- #
67
- # Time.new(1872, 12, 31).era_name # => RuntimeError
68
- def era_name(character = :kanji)
69
- unless %i[kanji romaji].include?(character)
70
- raise ArgumentError, 'invalid character'
71
- end
72
-
73
- current_era.send("#{character}_name")
74
- end
75
-
76
- # Returns the Japanese year since 1 January 1873 (Meiji 6).
77
- #
78
- # Time.new(2019, 5, 1).era_year # => 1
79
- # Time.new(2019, 4, 30).era_year # => 31
80
- # Time.new(1989, 1, 7).era_year # => 64
81
- # Time.new(1926, 12, 24).era_year # => 15
82
- # Time.new(1912, 7, 29).era_year # => 45
83
- #
84
- # Raises an error when the Japanese year cannot be found.
85
- #
86
- # Time.new(1872, 12, 31).era_year # => RuntimeError
87
- def era_year
88
- year - current_era.beginning_of_period.year + 1
44
+ string = super(format)
45
+ string.gsub(era_pattern, era_conversion)
89
46
  end
90
47
 
91
48
  private
92
49
 
93
- def current_era
94
- error_proc = proc { raise "#{self.class.name.downcase} out of range" }
95
- error_proc.call if self.to_date < MEIJI_6
96
- PERIODS.find(error_proc) do |period|
97
- period.beginning_of_period <= self.to_date
98
- end
99
- end
100
-
101
- def era_kanji_name
102
- era_name(:kanji)
103
- end
104
-
105
- def era_romaji_name
106
- era_name(:romaji)
107
- end
108
-
109
- def era_romaji_upcase_name
110
- era_romaji_name.upcase
111
- end
112
-
113
- def era_romaji_abbreviation
114
- era_romaji_name[0]
115
- end
116
-
117
- def era_year_string
118
- '%-d' % era_year
119
- end
120
-
121
- def era_year_zero_padded_string
122
- '%02d' % era_year
123
- end
124
-
125
- def era_year_blank_padded_string
126
- '%2d' % era_year
127
- end
128
-
50
+ # Returns a hash representing the format directives of the Japanese era.
129
51
  def era_conversion
130
52
  {
131
53
  '%JN' => era_kanji_name,
54
+ '%Jn' => era_kanji_abbreviation,
132
55
  '%JR' => era_romaji_name,
133
- '%^JR' => era_romaji_upcase_name,
56
+ '%^JR' => era_romaji_uppercased_name,
134
57
  '%Jr' => era_romaji_abbreviation,
135
58
  '%Jy' => era_year_zero_padded_string,
136
59
  '%-Jy' => era_year_string,
137
- '%_Jy' => era_year_blank_padded_string,
138
- '%K' => era_kanji_name,
139
- '%O' => era_romaji_name,
140
- '%^O' => era_romaji_upcase_name,
141
- '%o' => era_romaji_abbreviation,
142
- '%J' => era_year_zero_padded_string,
143
- '%-J' => era_year_string,
144
- '%_J' => era_year_blank_padded_string
60
+ '%_Jy' => era_year_blank_padded_string
145
61
  }
146
62
  end
147
63
 
64
+ # Returns a Regexp object representing the format directives of
65
+ # the day of the week
66
+ # (/%JN|%Jn|%JR|%^JR|%Jr|%Jy|%-Jy|%_Jy/).
148
67
  def era_pattern
149
68
  Regexp.union(era_conversion.keys)
150
69
  end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JapaneseCalendar
4
+ module Era #:nodoc:
5
+ Period = Struct.new(:beginning_of_period, :kanji_name, :romaji_name)
6
+
7
+ PERIODS = [
8
+ Period.new(Date.new(2019, 5, 1), '令和', 'Reiwa').freeze,
9
+ Period.new(Date.new(1989, 1, 8), '平成', 'Heisei').freeze,
10
+ Period.new(Date.new(1926, 12, 25), '昭和', 'Showa').freeze,
11
+ Period.new(Date.new(1912, 7, 30), '大正', 'Taisho').freeze,
12
+ Period.new(Date.new(1868, 1, 25), '明治', 'Meiji').freeze
13
+ ].freeze
14
+
15
+ private_constant :Period, :PERIODS
16
+
17
+ # Calculations module.
18
+ module Calculations
19
+ MEIJI_6 = Date.new(1873, 1, 1)
20
+
21
+ private_constant :MEIJI_6
22
+
23
+ # Returns the Japanese era name (nengo) since 1 January 1873 (Meiji 6).
24
+ #
25
+ # reiwa = Time.new(2019, 5, 1) # => 2019-05-01 00:00:00 +0900
26
+ # reiwa.era_name # => "令和"
27
+ # reiwa.era_name(:romaji) # => "Reiwa"
28
+ #
29
+ # heisei = Time.new(1989, 1, 8) # => 1989-01-08 00:00:00 +0900
30
+ # heisei.era_name # => "平成"
31
+ # heisei.era_name(:romaji) # => "Heisei"
32
+ #
33
+ # showa = Time.new(1926, 12, 25) # => 1926-12-25 00:00:00 +0900
34
+ # showa.era_name # => "昭和"
35
+ # showa.era_name(:romaji) # => "Showa"
36
+ #
37
+ # taisho = Time.new(1912, 7, 30) # => 1912-07-30 00:00:00 +0900
38
+ # taisho.era_name # => "大正"
39
+ # taisho.era_name(:romaji) # => "Taisho"
40
+ #
41
+ # meiji = Time.new(1873, 1, 1) # => 1873-01-01 00:00:00 +0900
42
+ # meiji.era_name # => "明治"
43
+ # meiji.era_name(:romaji) # => "Meiji"
44
+ #
45
+ # Raises an error when the Japanese era name cannot be found.
46
+ #
47
+ # Time.new(1872, 12, 31).era_name # => RuntimeError
48
+ def era_name(character = :kanji)
49
+ unless %i[kanji romaji].include?(character)
50
+ raise ArgumentError, 'invalid character'
51
+ end
52
+
53
+ current_era.send("#{character}_name")
54
+ end
55
+
56
+ # Returns the year of the Japanese era since 1 January 1873 (Meiji 6).
57
+ #
58
+ # Time.new(2019, 5, 1).era_year # => 1
59
+ # Time.new(2019, 4, 30).era_year # => 31
60
+ # Time.new(1989, 1, 7).era_year # => 64
61
+ # Time.new(1926, 12, 24).era_year # => 15
62
+ # Time.new(1912, 7, 29).era_year # => 45
63
+ #
64
+ # Raises an error when the year of the Japanese era cannot be found.
65
+ #
66
+ # Time.new(1872, 12, 31).era_year # => RuntimeError
67
+ def era_year
68
+ year - current_era.beginning_of_period.year + 1
69
+ end
70
+
71
+ private
72
+
73
+ def current_era
74
+ error_proc = proc { raise "#{self.class.name.downcase} out of range" }
75
+ error_proc.call if to_date < MEIJI_6
76
+ PERIODS.find(error_proc) do |period|
77
+ period.beginning_of_period <= to_date
78
+ end
79
+ end
80
+
81
+ # Returns a string representing the full name of the Japanese era in
82
+ # Kanji ("令和").
83
+ def era_kanji_name
84
+ era_name(:kanji)
85
+ end
86
+
87
+ # Returns a string representing the abbreviated name of the Japanese era
88
+ # in Kanji ("令").
89
+ def era_kanji_abbreviation
90
+ era_kanji_name[0]
91
+ end
92
+
93
+ # Returns a string representing the full name of the Japanese era in
94
+ # Romaji ("Reiwa").
95
+ def era_romaji_name
96
+ era_name(:romaji)
97
+ end
98
+
99
+ # Returns a string representing the uppercased full name of the Japanese
100
+ # era in Romaji ("REIWA").
101
+ def era_romaji_uppercased_name
102
+ era_romaji_name.upcase
103
+ end
104
+
105
+ # Returns a string representing the abbreviated name of the Japanese era
106
+ # in Romaji ("R").
107
+ def era_romaji_abbreviation
108
+ era_romaji_name[0]
109
+ end
110
+
111
+ # Returns a string representing the year of the Japanese era ("1")
112
+ def era_year_string
113
+ format('%-d', era_year)
114
+ end
115
+
116
+ # Returns a string representing the zero-padded year of the Japanese era
117
+ # ("01").
118
+ def era_year_zero_padded_string
119
+ format('%02d', era_year)
120
+ end
121
+
122
+ # Returns a string representing the blank-padded year of the Japanese era
123
+ # (" 1").
124
+ def era_year_blank_padded_string
125
+ format('%2d', era_year)
126
+ end
127
+ end
128
+ end
129
+ end