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

Class Method Summary collapse

Class Method Details

._format_time_directive(key, opt, time) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/wareki/utils.rb', line 176

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
    "#{YaKansuji.to_kan(time.hour, :simple)}時#{YaKansuji.to_kan(time.min, :simple)}分" \
    "#{YaKansuji.to_kan(time.sec, :simple)}秒"
  when :TH  then i2z(time.hour)
  when :THk then YaKansuji.to_kan(time.hour, :simple)
  when :TM  then i2z(time.min)
  when :TMk then YaKansuji.to_kan(time.min, :simple)
  when :TS  then i2z(time.sec)
  when :TSk then YaKansuji.to_kan(time.sec, :simple)
  end
end

._last_day_of_month_from_defs(year, month, is_leap) ⇒ Object



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

def _last_day_of_month_from_defs(year, month, is_leap)
  yobj = YEAR_BY_NUM[year] or
    raise UnsupportedDateRange, "Cannot find year #{year}"
  month_idx = month - 1
  month_idx += 1 if is_leap || (yobj.leap_month && yobj.leap_month < month)
  yobj.month_days[month_idx]
end

._last_day_of_month_gregorian(year, month) ⇒ Object



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

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

._time_match_to_s(match) ⇒ Object



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

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



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

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



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

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



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

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

.alt_month_name_to_i(name) ⇒ Object



63
64
65
66
# File 'lib/wareki/utils.rb', line 63

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



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

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



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

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



172
173
174
# File 'lib/wareki/utils.rb', line 172

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



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/wareki/utils.rb', line 92

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]

  yobj = find_year(d) or raise UnsupportedDateRange, "Unsupported date: #{d.inspect}"
  month = 0
  if yobj.month_starts.last <= d.jd
    month = yobj.month_starts.count
  else
    month = yobj.month_starts.find_index { |m| d.jd <= (m - 1) }
  end
  month_start = yobj.month_starts[month - 1]
  is_leap = (yobj.leap_month == (month - 1))
  yobj.leap_month && yobj.leap_month < month and
    month -= 1
  [yobj.year, month, d.jd - month_start + 1, is_leap]
end

.find_era(d) ⇒ Object



117
118
119
120
121
122
123
124
125
# File 'lib/wareki/utils.rb', line 117

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

.find_year(d) ⇒ Object



111
112
113
114
115
# File 'lib/wareki/utils.rb', line 111

def find_year(d)
  jd = _to_jd(d)
  jd < YEAR_DEFS.first.start and return nil
  YEAR_DEFS.bsearch { |y| y.end >= jd }
end

.i2z(num) ⇒ Object



127
128
129
# File 'lib/wareki/utils.rb', line 127

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

.i_to_kan(*args) ⇒ Object

DEPRECATED



200
201
202
203
# File 'lib/wareki/utils.rb', line 200

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



131
132
133
134
135
136
137
138
# File 'lib/wareki/utils.rb', line 131

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



194
195
196
197
# File 'lib/wareki/utils.rb', line 194

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



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

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



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

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")。



143
144
145
146
# File 'lib/wareki/utils.rb', line 143

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



161
162
163
164
165
166
167
168
169
170
# File 'lib/wareki/utils.rb', line 161

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