Module: Wareki::Utils

Defined in:
lib/wareki/utils.rb

Overview

Static utility methods.

Constant Summary collapse

TIME_FORMAT_DIRECTIVE_REGEX =
/%J(-|[_0]{0,2}[0-9]*|)(T(?:[fF]|[HMS]k?))/.freeze
TIME_FORMAT_EXPANSION_REGEX =
/(?<!%)(?:%%)*\K#{TIME_FORMAT_DIRECTIVE_REGEX}/.freeze
SIMPLE_KANSUJI_CACHE =
(0..99).map { |num| YaKansuji.to_kan(num, :simple).freeze }.freeze

Class Method Summary collapse

Class Method Details

._format_time_directive(key, opt, time) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/wareki/utils.rb', line 165

def _format_time_directive(key, opt, time)
  case key.to_sym
  when :Tf
    nf = number_format(opt)
    Kernel.format("#{nf}#{nf}#{nf}", time.hour, time.min, time.sec)
  when :TF
    "#{to_simple_kan(time.hour)}#{to_simple_kan(time.min)}#{to_simple_kan(time.sec)}"
  when :TH  then i2z(time.hour)
  when :THk then to_simple_kan(time.hour)
  when :TM  then i2z(time.min)
  when :TMk then to_simple_kan(time.min)
  when :TS  then i2z(time.sec)
  when :TSk then to_simple_kan(time.sec)
  end
end

._last_day_of_month_from_defs(year, month, is_leap) ⇒ Object



26
27
28
29
# File 'lib/wareki/utils.rb', line 26

def _last_day_of_month_from_defs(year, month, is_leap)
  Calendar.last_day_of_month(year, month, is_leap) or
    raise UnsupportedDateRange, "Cannot find year #{year}"
end

._last_day_of_month_gregorian(year, month) ⇒ Object



22
23
24
# File 'lib/wareki/utils.rb', line 22

def _last_day_of_month_gregorian(year, month)
  ::Date.new(year, month, -1, ::Date::GREGORIAN).day
end

._time_match_to_s(match) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/wareki/utils.rb', line 137

def _time_match_to_s(match)
  return '12:00' if match[:noon]

  hour = k2i(match[:hour])
  hour += 12 if match[:ampm] == '午後' && hour < 12
  min = 0
  min = 30 if match[:half]
  min = k2i(match[:min]) if match[:min]
  return Kernel.format('%<hour>02d:%<min>02d', hour: hour, min: min) unless match[:sec]

  Kernel.format('%<hour>02d:%<min>02d:%<sec>02d', hour: hour, min: min, sec: k2i(match[:sec]))
end

._to_date(d) ⇒ Object



70
71
72
73
74
75
76
77
78
# File 'lib/wareki/utils.rb', line 70

def _to_date(d)
  if d.is_a? ::Date
    d # nothing to do
  elsif d.is_a?(Time)
    d.to_date
  else
    ::Date.jd(d.to_i)
  end
end

._to_jd(d) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/wareki/utils.rb', line 80

def _to_jd(d)
  if d.is_a? ::Date
    d.jd
  elsif d.is_a?(Time)
    d.to_date.jd
  else
    d.to_i
  end
end

.alt_month_name(month) ⇒ Object



66
67
68
# File 'lib/wareki/utils.rb', line 66

def alt_month_name(month)
  ALT_MONTH_NAME[month - 1]
end

.alt_month_name_to_i(name) ⇒ Object



61
62
63
64
# File 'lib/wareki/utils.rb', line 61

def alt_month_name_to_i(name)
  i = ALT_MONTH_NAME.index(name) or return false
  i + 1
end

.civil_to_era_year(era_name, year) ⇒ Object



42
43
44
45
46
47
48
49
50
51
# File 'lib/wareki/utils.rb', line 42

def civil_to_era_year(era_name, year)
  era_name = era_name.to_s
  return year if ['', '西暦'].include?(era_name)
  return -year if era_name == '紀元前'
  return year - IMPERIAL_START_YEAR if IMPERIAL_ERA_NAMES.include?(era_name)

  era = ERA_BY_NAME[era_name] or
    raise ArgumentError, "Undefined era '#{era_name}'"
  year - era.year + 1
end

.era_year_to_civil(era_name, era_year) ⇒ Object



31
32
33
34
35
36
37
38
39
40
# File 'lib/wareki/utils.rb', line 31

def era_year_to_civil(era_name, era_year)
  era_name = era_name.to_s
  return era_year if ['', '西暦'].include?(era_name)
  return -era_year if era_name == '紀元前'
  return era_year + IMPERIAL_START_YEAR if IMPERIAL_ERA_NAMES.include?(era_name)

  era = ERA_BY_NAME[era_name] or
    raise ArgumentError, "Undefined era '#{era_name}'"
  era.year + era_year - 1
end

.expand_time_format(format_str, time) ⇒ Object



161
162
163
# File 'lib/wareki/utils.rb', line 161

def expand_time_format(format_str, time)
  format_str.to_str.gsub(TIME_FORMAT_EXPANSION_REGEX) { _format_time_directive($2, $1, time) || $& }
end

.find_date_ary(d) ⇒ Object



90
91
92
93
94
95
96
97
# File 'lib/wareki/utils.rb', line 90

def find_date_ary(d)
  d = _to_date(d).new_start(::Date::GREGORIAN)
  d.jd >= GREGORIAN_START and
    return [d.year, d.month, d.day, false]

  Calendar.find_date_ary(d.jd) or
    raise UnsupportedDateRange, "Unsupported date: #{d.inspect}"
end

.find_era(d) ⇒ Object



99
100
101
102
103
104
105
106
107
# File 'lib/wareki/utils.rb', line 99

def find_era(d)
  jd = _to_jd(d)
  ERA_DEFS.reverse_each do |e|
    e.start > jd and next
    e.end < jd and next
    return e
  end
  nil
end

.i2z(num) ⇒ Object



109
110
111
# File 'lib/wareki/utils.rb', line 109

def i2z(num)
  num.to_s.tr('0123456789', '0123456789')
end

.i_to_kan(*args) ⇒ Object

DEPRECATED



188
189
190
191
# File 'lib/wareki/utils.rb', line 188

def i_to_kan(*args)
  warn '[DEPRECATED] Wareki::Utils.i_to_kan: Please use ya_kansuji gem to handle kansuji'
  YaKansuji.to_kan(*args)
end

.k2i(str) ⇒ Object



113
114
115
116
117
118
119
120
# File 'lib/wareki/utils.rb', line 113

def k2i(str)
  str = str.to_s.strip
  if %w(  ).member? str
    1
  else
    YaKansuji.to_i str
  end
end

.kan_to_i(*args) ⇒ Object

DEPRECATED



182
183
184
185
# File 'lib/wareki/utils.rb', line 182

def kan_to_i(*args)
  warn '[DEPRECATED] Wareki::Utils.kan_to_i: Please use ya_kansuji gem to handle kansuji'
  k2i(*args)
end

.last_day_of_era_month(era_name, civil_year, month, is_leap) ⇒ Object



53
54
55
56
57
58
59
# File 'lib/wareki/utils.rb', line 53

def last_day_of_era_month(era_name, civil_year, month, is_leap)
  if WESTERN_ERA_NAMES.include?(era_name.to_s)
    ::Date.new(civil_year, month, -1, ::Date::ITALY).day
  else
    last_day_of_month(civil_year, month, is_leap)
  end
end

.last_day_of_month(year, month, is_leap) ⇒ Object



14
15
16
17
18
19
20
# File 'lib/wareki/utils.rb', line 14

def last_day_of_month(year, month, is_leap)
  if year >= GREGORIAN_START_YEAR
    _last_day_of_month_gregorian(year, month)
  else
    _last_day_of_month_from_defs(year, month, is_leap)
  end
end

.normalize_time(str) ⇒ Object

日本語の時刻表記 (漢数字・全角数字の時分秒、午前/午後、半、正午) を 等価な "HH:MM(:SS)" 表記へ置換する。値の範囲チェックは行わず、 妥当性判断は Ruby 標準パーサに委ねる (二十五時 -> "25:00")。



132
133
134
135
# File 'lib/wareki/utils.rb', line 132

def normalize_time(str)
  str.to_s =~ TIME_PARSE_QUICK_FILTER or return str
  str.to_s.sub(TIME_REGEX) { _time_match_to_s(Regexp.last_match) }
end

.number_format(opt) ⇒ Object



150
151
152
153
154
155
156
157
158
159
# File 'lib/wareki/utils.rb', line 150

def number_format(opt)
  case opt
  when '', '0', '_0' then '%02d'
  when '-'           then '%d'
  when /_\Z/         then '%2d'
  when /0?_/         then "%#{opt.sub(/0?_/, '')}d"
  when /_?0/         then "%#{opt.sub(/_?0/, '0')}d"
  else "%0#{opt}d"
  end
end

.to_simple_kan(num) ⇒ Object



122
123
124
125
126
127
# File 'lib/wareki/utils.rb', line 122

def to_simple_kan(num)
  return SIMPLE_KANSUJI_CACHE[num].dup if
    num.is_a?(Integer) && num >= 0 && num < SIMPLE_KANSUJI_CACHE.length

  YaKansuji.to_kan(num, :simple)
end