when_exe 0.2.100 → 0.3.1

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.
Files changed (193) hide show
  1. data/LICENSE.ja.txt +25 -25
  2. data/LICENSE.txt +31 -31
  3. data/bin/irb.rc +5 -0
  4. data/bin/locales.rb +2 -2
  5. data/bin/when.rb +16 -0
  6. data/bin/when.rb.config +7 -0
  7. data/lib/when_exe.rb +616 -14
  8. data/lib/when_exe/basictypes.rb +615 -0
  9. data/lib/when_exe/calendartypes.rb +1700 -0
  10. data/lib/when_exe/coordinates.rb +1936 -0
  11. data/lib/when_exe/core/compatibility.rb +54 -0
  12. data/lib/when_exe/core/duration.rb +72 -72
  13. data/lib/when_exe/core/extension.rb +382 -0
  14. data/lib/when_exe/ephemeris.rb +1845 -0
  15. data/lib/when_exe/googlecalendar.rb +140 -0
  16. data/lib/when_exe/icalendar.rb +1587 -0
  17. data/lib/when_exe/inspect.rb +1237 -0
  18. data/lib/when_exe/locales/af.rb +90 -0
  19. data/lib/when_exe/locales/ar.rb +145 -0
  20. data/lib/when_exe/locales/az.rb +90 -0
  21. data/lib/when_exe/locales/bg.rb +90 -0
  22. data/lib/when_exe/locales/bn.rb +94 -0
  23. data/lib/when_exe/locales/bs.rb +121 -0
  24. data/lib/when_exe/locales/ca.rb +92 -0
  25. data/lib/when_exe/locales/cs.rb +107 -0
  26. data/lib/when_exe/locales/cy.rb +150 -0
  27. data/lib/when_exe/locales/da.rb +84 -0
  28. data/lib/when_exe/locales/de.rb +92 -0
  29. data/lib/when_exe/locales/de_AT.rb +92 -0
  30. data/lib/when_exe/locales/de_CH.rb +92 -0
  31. data/lib/when_exe/locales/el.rb +93 -0
  32. data/lib/when_exe/locales/en.rb +88 -0
  33. data/lib/when_exe/locales/en_AU.rb +88 -0
  34. data/lib/when_exe/locales/en_CA.rb +88 -0
  35. data/lib/when_exe/locales/en_GB.rb +88 -0
  36. data/lib/when_exe/locales/en_IN.rb +88 -0
  37. data/lib/when_exe/locales/en_NZ.rb +88 -0
  38. data/lib/when_exe/locales/eo.rb +89 -0
  39. data/lib/when_exe/locales/es.rb +84 -0
  40. data/lib/when_exe/locales/es_419.rb +84 -0
  41. data/lib/when_exe/locales/es_AR.rb +84 -0
  42. data/lib/when_exe/locales/es_CL.rb +84 -0
  43. data/lib/when_exe/locales/es_CO.rb +84 -0
  44. data/lib/when_exe/locales/es_MX.rb +84 -0
  45. data/lib/when_exe/locales/es_PE.rb +85 -0
  46. data/lib/when_exe/locales/es_VE.rb +84 -0
  47. data/lib/when_exe/locales/et.rb +94 -0
  48. data/lib/when_exe/locales/eu.rb +95 -0
  49. data/lib/when_exe/locales/fa.rb +80 -0
  50. data/lib/when_exe/locales/fi.rb +89 -0
  51. data/lib/when_exe/locales/fr.rb +88 -0
  52. data/lib/when_exe/locales/fr_CA.rb +88 -0
  53. data/lib/when_exe/locales/fr_CH.rb +88 -0
  54. data/lib/when_exe/locales/gl.rb +81 -0
  55. data/lib/when_exe/locales/he.rb +84 -0
  56. data/lib/when_exe/locales/hi.rb +80 -0
  57. data/lib/when_exe/locales/hi_IN.rb +84 -0
  58. data/lib/when_exe/locales/hr.rb +128 -0
  59. data/lib/when_exe/locales/hu.rb +84 -0
  60. data/lib/when_exe/locales/id.rb +89 -0
  61. data/lib/when_exe/locales/is.rb +89 -0
  62. data/lib/when_exe/locales/it.rb +87 -0
  63. data/lib/when_exe/locales/it_CH.rb +87 -0
  64. data/lib/when_exe/locales/ja.rb +78 -0
  65. data/lib/when_exe/locales/kn.rb +86 -0
  66. data/lib/when_exe/locales/ko.rb +78 -0
  67. data/lib/when_exe/locales/links.rb +2342 -0
  68. data/lib/when_exe/locales/lo.rb +123 -0
  69. data/lib/when_exe/locales/locales.rb +91 -0
  70. data/lib/when_exe/locales/lt.rb +111 -0
  71. data/lib/when_exe/locales/lv.rb +118 -0
  72. data/lib/when_exe/locales/mk.rb +93 -0
  73. data/lib/when_exe/locales/mn.rb +80 -0
  74. data/lib/when_exe/locales/nb.rb +81 -0
  75. data/lib/when_exe/locales/ne.rb +81 -0
  76. data/lib/when_exe/locales/nl.rb +92 -0
  77. data/lib/when_exe/locales/nn.rb +73 -0
  78. data/lib/when_exe/locales/or.rb +84 -0
  79. data/lib/when_exe/locales/pl.rb +128 -0
  80. data/lib/when_exe/locales/pt.rb +88 -0
  81. data/lib/when_exe/locales/pt_BR.rb +88 -0
  82. data/lib/when_exe/locales/rm.rb +143 -0
  83. data/lib/when_exe/locales/ro.rb +105 -0
  84. data/lib/when_exe/locales/ru.rb +128 -0
  85. data/lib/when_exe/locales/sk.rb +109 -0
  86. data/lib/when_exe/locales/sl.rb +122 -0
  87. data/lib/when_exe/locales/sr.rb +122 -0
  88. data/lib/when_exe/locales/sv.rb +83 -0
  89. data/lib/when_exe/locales/sw.rb +89 -0
  90. data/lib/when_exe/locales/th.rb +78 -0
  91. data/lib/when_exe/locales/tl.rb +99 -0
  92. data/lib/when_exe/locales/tr.rb +96 -0
  93. data/lib/when_exe/locales/uk.rb +128 -0
  94. data/lib/when_exe/locales/uz.rb +128 -0
  95. data/lib/when_exe/locales/vi.rb +94 -0
  96. data/lib/when_exe/locales/wo.rb +82 -0
  97. data/lib/when_exe/locales/zh_CN.rb +77 -0
  98. data/lib/when_exe/locales/zh_HK.rb +77 -0
  99. data/lib/when_exe/locales/zh_TW.rb +77 -0
  100. data/lib/when_exe/mini_application.rb +252 -0
  101. data/lib/when_exe/parts/enumerator.rb +472 -0
  102. data/lib/when_exe/parts/geometric_complex.rb +379 -0
  103. data/lib/when_exe/parts/locale.rb +513 -0
  104. data/lib/when_exe/parts/method_cash.rb +207 -0
  105. data/lib/when_exe/parts/resource.rb +806 -0
  106. data/lib/when_exe/parts/timezone.rb +182 -0
  107. data/lib/when_exe/region/bahai.rb +145 -0
  108. data/lib/when_exe/region/balinese.rb +627 -0
  109. data/lib/when_exe/region/chinese.rb +896 -0
  110. data/lib/when_exe/region/chinese_calendar.rb +919 -0
  111. data/lib/when_exe/region/chinese_epoch.rb +1245 -0
  112. data/lib/when_exe/region/christian.rb +644 -0
  113. data/lib/when_exe/region/far_east.rb +192 -0
  114. data/lib/when_exe/region/french.rb +66 -0
  115. data/lib/when_exe/region/geologicalage.rb +639 -0
  116. data/lib/when_exe/region/indian.rb +1066 -0
  117. data/lib/when_exe/region/iranian.rb +66 -0
  118. data/lib/when_exe/region/islamic.rb +105 -0
  119. data/lib/when_exe/region/japanese.rb +851 -0
  120. data/lib/when_exe/region/japanese_notes.rb +964 -0
  121. data/lib/when_exe/region/japanese_residues.rb +1149 -0
  122. data/lib/when_exe/region/javanese.rb +228 -0
  123. data/lib/when_exe/region/jewish.rb +127 -0
  124. data/lib/when_exe/region/korean.rb +267 -0
  125. data/lib/when_exe/region/m17n.rb +115 -0
  126. data/lib/when_exe/region/martian.rb +215 -0
  127. data/lib/when_exe/region/mayan.rb +122 -0
  128. data/lib/when_exe/region/moon.rb +333 -0
  129. data/lib/when_exe/region/nihon_shoki.rb +73 -0
  130. data/lib/when_exe/region/planets.rb +585 -0
  131. data/lib/when_exe/region/pope.rb +298 -0
  132. data/lib/when_exe/region/residue.rb +229 -0
  133. data/lib/when_exe/region/roman.rb +325 -0
  134. data/lib/when_exe/region/ryukyu.rb +98 -0
  135. data/lib/when_exe/region/shire.rb +254 -0
  136. data/lib/when_exe/region/sun.rb +210 -0
  137. data/lib/when_exe/region/thai.rb +227 -0
  138. data/lib/when_exe/region/tibetan.rb +233 -0
  139. data/lib/when_exe/region/v50.rb +111 -0
  140. data/lib/when_exe/region/vietnamese.rb +173 -0
  141. data/lib/when_exe/region/world.rb +197 -0
  142. data/lib/when_exe/timestandard.rb +547 -0
  143. data/lib/when_exe/tmduration.rb +330 -330
  144. data/lib/when_exe/tmobjects.rb +1295 -0
  145. data/lib/when_exe/tmposition.rb +1955 -0
  146. data/lib/when_exe/tmreference.rb +1547 -0
  147. data/lib/when_exe/version.rb +10 -3
  148. data/link_to_online_documents +4 -0
  149. data/test/examples/JapanHolidays.ics +456 -0
  150. data/test/examples/Millennium.ics +17 -0
  151. data/test/examples/NewYork.ics +61 -0
  152. data/test/examples/Residue.m17n +135 -0
  153. data/test/examples/Spatial.m17n +179 -0
  154. data/test/examples/Terms.m17n +39 -0
  155. data/test/examples/Test.ics +53 -0
  156. data/test/examples/USA-DST.ics +61 -0
  157. data/test/examples/geometric_complex.rb +41 -0
  158. data/test/examples/sample.xml +14 -0
  159. data/test/examples/today.rb +61 -0
  160. data/test/test.rb +54 -19
  161. data/test/test.rb.config +1 -0
  162. data/test/test/basictypes.rb +368 -0
  163. data/test/test/calendartypes.rb +57 -0
  164. data/test/test/coordinates.rb +380 -0
  165. data/test/test/ephemeris.rb +127 -0
  166. data/test/test/googlecalendar.rb +167 -0
  167. data/test/test/icalendar.rb +848 -0
  168. data/test/test/inspect.rb +115 -0
  169. data/test/test/parts.rb +480 -0
  170. data/test/test/region/chinese.rb +161 -0
  171. data/test/test/region/french.rb +33 -0
  172. data/test/test/region/geologicalage.rb +14 -0
  173. data/test/test/region/indian.rb +55 -0
  174. data/test/test/region/iran.rb +54 -0
  175. data/test/test/region/islamic.rb +18 -0
  176. data/test/test/region/japanese.rb +62 -0
  177. data/test/test/region/jewish.rb +61 -0
  178. data/test/test/region/m17n.rb +181 -0
  179. data/test/test/region/mayan.rb +78 -0
  180. data/test/test/region/moon.rb +14 -0
  181. data/test/test/region/planets.rb +14 -0
  182. data/test/test/region/residue.rb +123 -0
  183. data/test/test/region/sun.rb +14 -0
  184. data/test/test/region/thai.rb +94 -0
  185. data/test/test/region/tibetan.rb +30 -0
  186. data/test/test/tmobjects.rb +356 -57
  187. data/test/test/tmposition.rb +237 -0
  188. data/test/test/tmreference.rb +95 -0
  189. data/when_exe.gemspec +2 -2
  190. metadata +187 -7
  191. data/doc/COPYING +0 -31
  192. data/doc/COPYING.ja +0 -25
  193. data/doc/document_url +0 -1
@@ -0,0 +1,1237 @@
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ Copyright (C) 2011-2013 Takashi SUGA
4
+
5
+ You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
+ =end
7
+
8
+ module When
9
+ module Parts::Resource
10
+
11
+ #
12
+ # オブジェクトの内容を Hash 化
13
+ #
14
+ # @param [String, Integer] options {When::TM::TemporalPosition#_to_hash}に渡す
15
+ # @param [Hash] options 下記のとおり
16
+ # @option options [Boolean] :camel true ならシンボルを camel case にする
17
+ # @option options [String] :locale 文字列化の locale(指定なしは M17nオブジェクトに変換)
18
+ # @option options [Boolean] :simple true ならIRI の先頭部分を簡約表現にする
19
+ # @option options [Boolean] :residue true なら Residue をそのまま出力
20
+ # @option options [Object] :その他 各クラス#_to_hash を参照
21
+ #
22
+ # @return [Hash] (Whenモジュール内のクラスは文字列 or M17n化)
23
+ #
24
+ def to_hash(options={})
25
+ _m17n_form(_to_hash(options), options.kind_of?(Hash) ? options : {})
26
+ end
27
+
28
+ #
29
+ # オブジェクトの内容を JSON 化
30
+ #
31
+ # @param [Object] options #to_hash を参照
32
+ #
33
+ # @return [String] to_hash 結果を JSON文字列化したもの
34
+ #
35
+ def _to_json(options={})
36
+ JSON.dump(to_hash(options))
37
+ end
38
+
39
+ #
40
+ # _m17n_form のための要素生成
41
+ # @private
42
+ def _to_hash_value(options={})
43
+ @_pool ? When::Parts::Resource._path_with_prefix(self, options[:simple]) : self
44
+ end
45
+
46
+ private
47
+ #
48
+ # 時間位置オブジェクトの内容を Hash 化
49
+ #
50
+ # @param [Object] options #to_hash を参照
51
+ #
52
+ # @return [Hash]
53
+ # 各クラスの HashProperty に列挙した属性のうち値が false/nil でないものを
54
+ # 属性 => 値
55
+ # とする Hash
56
+ #
57
+ def _to_hash(options={})
58
+ hash = {}
59
+ self.class::HashProperty.each do |property|
60
+ method, skip = property
61
+ value = send(method)
62
+ hash[method] = value unless value == skip || value.class == skip
63
+ end
64
+ hash
65
+ end
66
+
67
+ #
68
+ # element を 文字列(M17n), Numeric あるいはそれらの Hash や Array に変換したもの
69
+ #
70
+ # @param [Object] element 変換元
71
+ # @param [Hash] options 下記の通り
72
+ # @option options [Boolean] :camel true ならシンボルを camel case にする
73
+ # @option options [String] :locale 文字列化の locale(指定なしは M17nオブジェクトに変換)
74
+ # @option options [Boolean] :simple true ならIRI の先頭部分を簡約表現にする
75
+ # @option options [Boolean] :residue true なら Residue をそのまま出力
76
+ #
77
+ # @return [Hash, Array] 変換結果
78
+ #
79
+ # @note element.events のある日付は _event_form で変換する
80
+ #
81
+ def _m17n_form(element, options={})
82
+ result = element.respond_to?(:_event_form) ? element._event_form(self) :
83
+ element.respond_to?(:_to_hash_value) ? element._to_hash_value(options) :
84
+ element.respond_to?(:label) && element.label ? element.label :
85
+ case element
86
+ when Hash ; Hash[*(element.keys.inject([]) { |s, k|
87
+ s + [_m17n_form(k, options), _m17n_form(element[k], options)]
88
+ })]
89
+ when Array ; element.map {|e| _m17n_form(e, options)}
90
+ when Class ; When::Parts::Resource._path_with_prefix(element, options[:simple])
91
+ when Symbol ; options[:camel] ? element.to_s.split(/_/).map {|e| e.capitalize}.join('').to_sym : element
92
+ when Numeric, FalseClass, TrueClass ; element
93
+ else ; element.to_s
94
+ end
95
+ result = result.translate(options[:locale]) if options[:locale] && result.kind_of?(When::BasicTypes::M17n)
96
+ result
97
+ end
98
+ end
99
+
100
+ module Coordinates
101
+
102
+ class Residue
103
+ # 多言語対応文字列化
104
+ #
105
+ # @return [When::BasicTypes::M17n]
106
+ #
107
+ def to_m17n
108
+ return m17n(@remainder.to_s) unless label
109
+ return label + "(#{difference})" unless @format
110
+ label[0...0] + (@format % [label, difference, difference+1])
111
+ end
112
+
113
+ # 文字列化
114
+ #
115
+ # @return [String]
116
+ #
117
+ def to_s
118
+ return @remainder.to_s unless label
119
+ return label.to_s + "(#{difference})" unless @format
120
+ (@format % [label, difference, difference+1]).to_s
121
+ end
122
+
123
+ #
124
+ # to_hash のための要素生成
125
+ # @private
126
+ def _to_hash_value(options={})
127
+ options[:residue] ? self : to_m17n
128
+ end
129
+ end
130
+
131
+ class Pair
132
+ #
133
+ # to_hash のための要素生成
134
+ # @private
135
+ def _to_hash_value(options={})
136
+ to_s
137
+ end
138
+ end
139
+ end
140
+
141
+ module TM
142
+ class TemporalPosition
143
+
144
+ AMPM = ['AM', 'PM'].map {|half| When::Parts::Resource._instance('_m:CalendarFormats::' + half)}
145
+ Format = {
146
+ 'a' => ['%s', 'a'], 'A' => ['%s', 'A'], 'b' => ['%s', 'b'], 'B' => ['%s', 'B'],
147
+ 'c' => When::Parts::Resource._instance('_m:CalendarFormats::DateTime'),
148
+ 'C' => ['%02d', 'C'], 'd' => ['%02d', 'd'], 'D' => '%m/%d/%y', 'e' => ['%2d', 'd'],
149
+ 'E' => ['%s', 'E'], 'F' => ['%s', 'F'], 'G' => ['%d', 'G'], 'g' => ['%02d', 'g'],
150
+ 'h' => '%b', 'H' => ['%02d', 'H'], 'I' => ['%02d', 'I'], 'j' => ['%03d', 'j'],
151
+ 'k' => ['%2d', 'H'], 'l' => ['%2d', 'I'], 'm' => ['%02d', 'm'], 'M' => ['%02d', 'M'],
152
+ 'n' => '\n', 'p' => ['%s', 'p'], 'P' => ['%s', 'P'], 'r' => '%I:%M:%S %p',
153
+ 'R' => '%H:%M', 's' => ['%d', 's'], 'S' => ['%02d', 'S'], 't' => '\t',
154
+ 'T' => '%H:%M:%S', 'u' => ['%d', 'u'], 'U' => ['%02d', 'U'], 'V' => ['%02d', 'V'],
155
+ 'w' => ['%d', 'w'], 'W' => ['%02d', 'W'],
156
+ 'x' => When::Parts::Resource._instance('_m:CalendarFormats::Date'),
157
+ 'X' => When::Parts::Resource._instance('_m:CalendarFormats::Time'),
158
+ 'y' => ['%02d', 'y'], 'Y' => ['%4d', 'Y'], 'z' => ['%s', 'z'], 'Z' => ['%s', 'Z'],
159
+ '+' => '%a %b %d %T %z %Y'
160
+ }
161
+
162
+ class << self
163
+
164
+ # strftime で用いる書式のハッシュ
165
+ attr_accessor :format
166
+
167
+ # When::TM::TemporalPosition Class のグローバルな設定を行う
168
+ #
169
+ # @param [Hash] format strftime で用いる記号の定義
170
+ #
171
+ # @return [void]
172
+ #
173
+ # @note format の指定がない場合、format は Format(モジュール定数)と解釈する
174
+ #
175
+ def _setup_(format=nil)
176
+ @format = format ? Format.merge(format) : Format
177
+ end
178
+ end
179
+
180
+ #
181
+ # 暦法名
182
+ #
183
+ # @return [Array<Class>] Class 暦法のクラスオブジェクト
184
+ #
185
+ def calendar_name
186
+ [self.class]
187
+ end
188
+
189
+ #
190
+ # 時法名
191
+ #
192
+ # @return [Array<String>] String 時法の IRI
193
+ #
194
+ def clock_name
195
+ [When::Parts::Resource._path_with_prefix(clock)]
196
+ end
197
+
198
+ #
199
+ # 参照ラベル
200
+ #
201
+ # @return [When::BasicTypes::M17n]
202
+ #
203
+ def reference_label
204
+ [When::BasicTypes::M17n.new(self.class.to_s.split(/::/)[-1])]
205
+ end
206
+
207
+ # 含まれる週
208
+ #
209
+ # @overload week_included(ord, wkst, opt, block)
210
+ # @param [Numeric, Range] ord 週の番号(default: 今週)
211
+ # 今週を 0 とする週番号(Integer) または週番号の範囲(Range)
212
+ # -1 - 先週
213
+ # 0 - 今週
214
+ # +1 - 来週
215
+ # @param [String] wkst 週の開始曜日(defaultは 月曜)
216
+ # @param [When::CalendarTypes::CalendarNote] wkst 暦注オブジェクト
217
+ # @param [Array<When::CalendarTypes::CalendarNote, String>] wkst 暦注オブジェクトとそのイベントメソッド名
218
+ # (暦注オブジェクトは、そのIRI文字列を指定しても良い)
219
+ # @param [Hash] opt 下記の通り
220
+ # @option opt [Range] :Range 上位繰り返し範囲(ユリウス通日...ユリウス通日)
221
+ # @param [Block] block
222
+ #
223
+ # @note 引数 ord, wkst, opt はそのクラスで位置づけを判断するため、引数の順序は任意(省略も可)
224
+ #
225
+ # @return [Range] 含まれる週を範囲として表現する Range (block 指定なし)
226
+ # @return [Array] 含まれる週の各日をブロックに渡した結果の Array (block 指定あり)
227
+ #
228
+ def week_included(*args)
229
+ begin
230
+ first, length, wkst, opt = _range(args, 'MO')
231
+ case wkst
232
+ when When::Coordinates::Residue
233
+ today = self.floor
234
+ begun = today.succ & wkst >> first-1
235
+ unless @frame.equal?(begun.frame)
236
+ begun = (@frame ^ today).succ & wkst >> first-1
237
+ middle = today
238
+ end
239
+ ended = begun.succ & wkst >> length-1
240
+ else
241
+ begun = ended = nil
242
+ if first <= 0
243
+ it = wkst.enum_for(self.floor, :reverse)
244
+ (1-first).times do
245
+ begun = it.next
246
+ end
247
+ else
248
+ it = wkst.enum_for(self.floor, :forward)
249
+ first.times do
250
+ begun = it.next
251
+ end
252
+ end
253
+ it = wkst.enum_for(begun, :forward)
254
+ (length+1).times do
255
+ ended = it.next
256
+ end
257
+ end
258
+ range = middle && block_given? ? [begun...middle, middle...ended] : [begun...ended]
259
+
260
+ rescue RangeError
261
+ range = [(@frame ^ self).week_included(*args)]
262
+ end
263
+
264
+ return range[0] unless block_given?
265
+
266
+ (range.inject([]) {|s,r| s + r.map { |date|
267
+ yield(date, !opt.key?(:Range) || opt[:Range].include?(date.to_i) ? DAY : nil)
268
+ }}).unshift(yield(range[0].first, WEEK)).compact
269
+ end
270
+
271
+ # 含まれる月
272
+ #
273
+ # @overload month_included(ord, wkst, opt, block)
274
+ # @param [Numeric, Range] ord 月の番号(default: 今月)
275
+ # 今月を 0 とする月番号(Integer) または月番号の範囲(Range)
276
+ # -1 - 先月
277
+ # 0 - 今月
278
+ # +1 - 来月
279
+ # @param [String] wkst 週の開始曜日(defaultはなし)
280
+ # @param [When::CalendarTypes::CalendarNote] wkst 暦注オブジェクト
281
+ # @param [Array<When::CalendarTypes::CalendarNote, String>] wkst 暦注オブジェクトとそのイベントメソッド名
282
+ # (暦注オブジェクトは、そのIRI文字列を指定しても良い)
283
+ # @param [Hash] opt 下記の通り
284
+ # @option opt [Range] :Range 上位繰り返し範囲(ユリウス通日...ユリウス通日)
285
+ # @param [Block] block
286
+ #
287
+ # @note 引数 ord, wkst, opt はそのクラスで位置づけを判断するため、引数の順序は任意(省略も可)
288
+ #
289
+ # @return [Range] 含まれる月を範囲として表現する Range (block 指定なし)
290
+ # @return [Array] 含まれる月の各日をブロックに渡した結果の Array (block 指定あり, wkst なし)
291
+ # @return [Array<Array>] 含まれる月の各日をブロックに渡した結果の 七曜表(block 指定あり, wkst あり)
292
+ #
293
+ def month_included(*args, &block)
294
+ first, length, wkst, opt = _range(args)
295
+ if wkst
296
+ (first...(first+length)).map {|i|
297
+ begun = self.floor(MONTH,DAY) + When::TM::PeriodDuration.new([0,i,0])
298
+ ended = begun + DurationP1M
299
+ ended = ended.prev until begun.cal_date[MONTH-1] == ended.cal_date[MONTH-1]
300
+ dates = [begun]
301
+ loop do
302
+ current = dates[-1].week_included(wkst)
303
+ if ((current.first.to_i)...(current.last.to_i)).include?(ended.to_i)
304
+ dates[-1] = ended
305
+ break (dates.map {|date| date.week_included(wkst, {:Range=>begun.to_i..ended.to_i}, &block)}).
306
+ unshift(yield(begun, MONTH)).compact
307
+ elsif wkst.kind_of?(When::Coordinates::Residue)
308
+ dates << dates[-1] + wkst.duration
309
+ else
310
+ it = wkst.enum_for(dates[-1], :forward)
311
+ begin
312
+ date = it.next
313
+ end while date.to_i == dates[-1].to_i
314
+ dates << date
315
+ end
316
+ end
317
+ }
318
+ else
319
+ begun = self.floor(MONTH,DAY) + When::TM::PeriodDuration.new([0, first, 0])
320
+ ended = begun + When::TM::PeriodDuration.new([0, length, 0])
321
+ if block_given?
322
+ (begun...ended).map do |date|
323
+ yield(date)
324
+ end
325
+ else
326
+ begun...ended
327
+ end
328
+ end
329
+ end
330
+
331
+ # 含まれる年
332
+ #
333
+ # @overload month_included(ord, wkst, opt, block)
334
+ # @param [Numeric, Range] ord 年の番号(default: 今年)
335
+ # 今年を 0 とする年番号(Integer) または年番号の範囲(Range)
336
+ # -1 - 先年
337
+ # 0 - 今年
338
+ # +1 - 来年
339
+ # @param [String] wkst 週の開始曜日(defaultはなし)
340
+ # @param [When::CalendarTypes::CalendarNote] wkst 暦注オブジェクト
341
+ # @param [Array<When::CalendarTypes::CalendarNote, String>] wkst 暦注オブジェクトとそのイベントメソッド名
342
+ # (暦注オブジェクトは、そのIRI文字列を指定しても良い)
343
+ # @param [Hash] opt 下記の通り
344
+ # @option opt [Range] :Range 上位繰り返し範囲(ユリウス通日...ユリウス通日)
345
+ # @param [Block] block
346
+ #
347
+ # @note 引数 ord, wkst, opt はそのクラスで位置づけを判断するため、引数の順序は任意(省略も可)
348
+ #
349
+ # @return [Range] 含まれる年を範囲として表現する Range (block 指定なし)
350
+ # @return [Array] 含まれる年の各日をブロックに渡した結果の Array (block 指定あり, wkst なし)
351
+ # @return [Array<Array>] 含まれる年の各日をブロックに渡した結果の 七曜表(block 指定あり, wkst あり)
352
+ #
353
+ def year_included(*args, &block)
354
+ first, length, wkst, opt = _range(args)
355
+ if wkst
356
+ (first...(first+length)).map {|i|
357
+ begun = _force_euqal_year(i)
358
+ ended = _force_euqal_year(i+1)
359
+ current = begun
360
+ result = [yield(begun, YEAR)]
361
+ while current < ended do
362
+ result << current.month_included(wkst, &block)
363
+ current += DurationP1M
364
+ end
365
+ result.compact
366
+ }
367
+ else
368
+ begun = _force_euqal_year(first)
369
+ ended = _force_euqal_year(first+length)
370
+ if block_given?
371
+ (begun...ended).map do |date|
372
+ yield(date)
373
+ end
374
+ else
375
+ begun...ended
376
+ end
377
+ end
378
+ end
379
+
380
+ # 指定の年初を探す
381
+ def _force_euqal_year(diff)
382
+ year = most_significant_coordinate * 1 + diff
383
+ date = (self + When::TM::PeriodDuration.new([diff,0,0])).floor(YEAR,DAY)
384
+ done = {}
385
+ loop do
386
+ case
387
+ when date.most_significant_coordinate * 1 == year
388
+ return date
389
+ when date.most_significant_coordinate * 1 > year
390
+ next_date = (date-When::DurationP1Y).floor(YEAR,DAY)
391
+ date = (date.to_i == next_date.to_i) ?
392
+ (date-When::DurationP1Y*2).floor(YEAR,DAY) :
393
+ next_date
394
+ else
395
+ next_date = (date+When::DurationP1Y).floor(YEAR,DAY)
396
+ date = (date.to_i == next_date.to_i) ?
397
+ (date+When::DurationP1Y*2).floor(YEAR,DAY) :
398
+ next_date
399
+ end
400
+ raise RangeError, "can't find target date: #{self} -> #{year}" if done.key?(date.to_i)
401
+ done[date.to_i] = true
402
+ end
403
+ end
404
+ private :_force_euqal_year
405
+
406
+ # 範囲の取得
407
+ def _range(args, wkst=nil)
408
+ ord = 0
409
+ opt = {}
410
+ args.each do |arg|
411
+ case arg
412
+ when Integer, Range ; ord = arg
413
+ when Hash ; opt = arg
414
+ else ; wkst = arg
415
+ end
416
+ end
417
+ wkst, method = wkst
418
+ wkst = When::Coordinates::Residue.day_of_week(wkst) || When.CalendarNote(wkst) if wkst
419
+ wkst = wkst[method] if method
420
+ return ord, 1, wkst, opt if ord.kind_of?(Integer)
421
+ length = ord.last - ord.first
422
+ length += 1 unless ord.exclude_end?
423
+ return ord.first, length, wkst, opt
424
+ end
425
+ private :_range
426
+
427
+ #
428
+ # 時間位置オブジェクトの暦注を取得し value を暦注の値 (String, When::BasicTypes::M17n or When::Coordinates::Residue)とする Hash で表現
429
+ #
430
+ # @param [String] options { :notes => String } という Hash の指定と等価
431
+ # @param [Integer] options { :indices => Integer } という Hash の指定と等価
432
+ # @param [Hash] options 下記のとおり
433
+ # @option options [When::CalendarTypes::CalendarNote, String] :calendar_note 暦注を計算する暦注オブジェクトまたはそのIRI
434
+ # @option options [Object] その他のキー {When::CalendarTypes::CalendarNote#notes} を参照
435
+ #
436
+ # @return [Array<Array<Hash{:note=>note, :value=>value}>>]
437
+ # [ note [String, When::BasicTypes::M17n] 暦注名 ]
438
+ # [ value [String, When::BasicTypes::M17n, When::Coordinates::Residue] 暦注の値 ]
439
+ #
440
+ def notes(options={})
441
+ _m17n_form(_notes(options), options.kind_of?(Hash) ? options : {})
442
+ end
443
+
444
+ #
445
+ # 時間位置オブジェクトの暦注を取得
446
+ #
447
+ # @param [String] options { :notes => String } という Hash の指定と等価
448
+ # @param [Integer] options { :indices => Integer } という Hash の指定と等価
449
+ # @param [Hash] options 下記のとおり
450
+ # @option options [When::CalendarTypes::CalendarNote, String] :calendar_note 暦注を計算する暦注オブジェクトまたはそのIRI
451
+ # @option options [Object] その他のキー {When::CalendarTypes::CalendarNote#notes} を参照
452
+ #
453
+ # @return [Array<Array<Hash{:note=>note, :value=>value}>>]
454
+ # [ note [String, When::BasicTypes::M17n, When::Coordinates::Residue] 暦注名 ]
455
+ # [ value [String, When::BasicTypes::M17n, When::Coordinates::Residue, When::TM::TemporalPosition] 暦注の値 ]
456
+ #
457
+ # @note
458
+ # When::TM::TemporalPosition の場合、events[0] に暦注名の入ったその暦注に該当する日付である。
459
+ # (例) Christian クラス で easter を計算した場合、当該年の復活祭の日付オブジェクトが返る。
460
+ # 暦注サブクラスの場合、要素が増えたり、:note の暦注要素の型が変わったりすることがある。
461
+ #
462
+ def _notes(options={})
463
+ _calendar_note(options).notes(self, options)
464
+ end
465
+
466
+ #
467
+ # 暦注の一致 or 不一致
468
+ #
469
+ # @param [String] options { :notes => String } または { :value => String } という Hash の指定と等価
470
+ # (指定の notes が存在する場合は前者、しない場合は後者)
471
+ # @param [Integer] options { :indices => Integer } という Hash の指定と等価
472
+ # @param [Hash] options 下記のとおり
473
+ # @option options [Object] :value 確認する暦注の値
474
+ # @option options [Object] その他のキー {When::CalendarTypes::CalendarNote#notes} を参照
475
+ #
476
+ # @return [Boolean]
477
+ # [ true - 暦注が一致 ]
478
+ # [ false - 暦注が不一致 ]
479
+ #
480
+ def note?(options={})
481
+ _calendar_note(options).note?(self, options)
482
+ end
483
+
484
+ # 指定の日時が指定イベントに該当するか?
485
+ #
486
+ # @param [String] options { :notes => String } または { :notes => String } または { :value => String } という Hash の指定と等価
487
+ # (指定の event が存在する場合は前者、指定の notes が存在する場合は中央、しない場合は後者)
488
+ # @param [Integer] options { :indices => Integer } という Hash の指定と等価
489
+ # @param [Hash] options 下記のとおり
490
+ # @option options [String] :event 確認するイベント名
491
+ # @option options [Object] :value 確認する暦注の値
492
+ # @option options [Object] その他のキー {When::CalendarTypes::CalendarNote#notes} を参照
493
+ #
494
+ # @return [Boolean]
495
+ # [ true - 該当する ]
496
+ # [ false - 該当しない ]
497
+ #
498
+ def is?(options=nil)
499
+ calendar_note = _calendar_note(options)
500
+ event =
501
+ case options
502
+ when String ; options
503
+ when Hash ; options.delete(:event)
504
+ else ; calendar_note.event
505
+ end
506
+ event.to_s =~ /^([^\d]+)/ && calendar_note.respond_to?($1.downcase) ?
507
+ calendar_note.include?(self, event) :
508
+ calendar_note.note?(self, options)
509
+ end
510
+
511
+ #
512
+ # 時間位置オブジェクトの内容を Hash 化
513
+ #
514
+ # @param [String] options { :notes => String } という Hash の指定と等価
515
+ # @param [Integer] options { :indices => Integer } という Hash の指定と等価
516
+ # @param [Hash] options 下記のとおり
517
+ # @option options [When::CalendarTypes::CalendarNote, String] :calendar_note 暦注を計算する暦注オブジェクトまたはそのIRI
518
+ # @option options [Object] その他のキー {When::CalendarTypes::CalendarNote#notes} を参照
519
+ #
520
+ # @return [Hash]
521
+ # - :sdn 日の通し番号 - ユリウス通日(Integer)
522
+ # - :calendar calendar_name の結果 - Array<暦法または暦年代(, 付属情報..)>
523
+ # - :notes Hash (の Array (の Array)) - _notes(options)
524
+ # clock が定義されている場合、さらに下記も出力する
525
+ # - :clock 時計(When::TM::Clock, When::V::Timezone, When::Parts::Timezone)
526
+ # - :clk_time to_clock_time の結果 - ( 日, 時, 分, 秒 )
527
+ # - :dynamical dynamical_time / 秒
528
+ # - :universal universal_time / 秒
529
+ #
530
+ def _to_hash(options={})
531
+ hash = super.update({
532
+ :sdn => to_i,
533
+ :calendar => calendar_name,
534
+ :notes => _notes(options)
535
+ })
536
+
537
+ hash.update({
538
+ :clock => clock,
539
+ :clk_time => to_clock_time,
540
+ :dynamical => dynamical_time * clock.second,
541
+ :universal => universal_time * clock.second
542
+ }) if clock
543
+ hash
544
+ end
545
+
546
+ # 多言語対応文字列化 - When.exe Standard Representation により多言語対応文字列化する
547
+ #
548
+ # @overload to_m17n()
549
+ #
550
+ # @return [When::BasicTypes::M17n]
551
+ #
552
+ def to_m17n(*args)
553
+ return m17n(I[@indeterminated_position]) if [Unknown, Max, Min].include?(@indeterminated_position)
554
+ return m17n(_to_s)
555
+ end
556
+ # @private
557
+ alias :_to_s :to_s
558
+
559
+ # 文字列化 - When.exe Standard Representation により文字列化する
560
+ #
561
+ # @overload to_s()
562
+ #
563
+ # @return [String]
564
+ #
565
+ def to_s(*args)
566
+ to_m17n(*args).to_s
567
+ end
568
+
569
+ # URI要素化 - URI表現の要素として用いる形式に変換
570
+ #
571
+ # @overload to_uri()
572
+ #
573
+ # @return [String]
574
+ #
575
+ def to_uri(*args)
576
+ _to_uri(to_s(*args))
577
+ end
578
+
579
+ # URI要素化(日付のみ) - 日付の部分をURI表現の要素として用いる形式に変換
580
+ #
581
+ # @overload to_date_uri()
582
+ #
583
+ # @return [String]
584
+ #
585
+ def to_date_uri(*args)
586
+ _to_uri(to_s(*args).sub(/T([-+][\d:]+|Z|MTC)$/,''))
587
+ end
588
+
589
+ def _to_uri(date)
590
+ uri = date.gsub(/\./, '-').gsub(/%/, '@')
591
+ unless @calendar_era_name || @frame == When.Calendar('Gregorian')
592
+ uri += '^^' + @frame.iri.gsub(/\?/, '%3F').gsub('.', '@').split(/\//)[-1]
593
+ end
594
+ uri
595
+ end
596
+ private :_to_uri
597
+
598
+ # 指定の書式による多言語対応文字列化 - pattern で指定した書式で多言語対応文字列化する
599
+ #
600
+ # @param [When::BasicTypes::M17n] pattern 書式
601
+ # @param [String, Array<String>] locale 文字列化を行う locale の指定(デフォルト : オブジェクト生成時に保持している locale すべて)
602
+ #
603
+ # @return [When::BasicTypes::M17n]
604
+ #
605
+ def strftime(pattern, locale=nil)
606
+ pattern = m17n([pattern]*self.keys.length, nil, nil, {:locale=>self.keys}) if pattern.instance_of?(String)
607
+ pattern._printf([], locale) do |k, *t|
608
+ _strftime(k, pattern, [''])
609
+ end
610
+ end
611
+
612
+ # strftime で扱う項の値を取得する
613
+ #
614
+ # @param [String] designator 項目名
615
+ # @param [String] locale 文字列化を行う場合の locale の指定(デフォルト to_s(代表値))
616
+ # @param [Integer] d 日付が'年月日'、時刻が'時分秒'でない表現のための桁位置変更指示
617
+ # [ 年月に付く場合 - 大きいほうに位置をずらす ]
618
+ # [ 分秒に付く場合 - 小さいほうに位置をずらす ]
619
+ # @param [Integer] e 月の省略名の文字数
620
+ #
621
+ # @return [designator に依存]
622
+ #
623
+ def term(designator, locale=nil, d=0, e=3)
624
+ designator = When::Parts::Locale.translate(designator,locale)
625
+ case designator
626
+ # 現在のロケールにおける曜日の省略名
627
+ when 'a' ; When.Resource('_co:CommonResidue::Abbr_Day')[to_i % 7].translate(locale)
628
+ # 現在のロケールにおける曜日の完全な名前
629
+ when 'A' ; When.Resource('_co:CommonResidue::Week')[to_i % 7].label.translate(locale)
630
+ when 'b' ; (name(MONTH-d).translate(locale))[/^.{1,#{e}}/] # 現在のロケールにおける月の省略名
631
+ when 'B' ; (name(MONTH-d).translate(locale)) # 現在のロケールにおける月の完全な名前
632
+ when 'C' ; year(d).div(100) # 世紀 (西暦年の上 2 桁)
633
+ when 'd' ; day(d) # 月内通算日
634
+ when 'E' ; Array(calendar_era_name)[0].translate(locale)# 年号
635
+ when 'F' ; floor(DAY).to_m17n.translate(locale) # ISO 8601 形式の日付フォーマット
636
+ when 'G' ; cwyear(d) # ISO 8601 週単位表記の年
637
+ when 'g' ; cwyear(d) % 100 # ISO 8601 週単位表記の年の下2桁
638
+ when 'H' ; hour(d) # 24 時間表記での時
639
+ when 'I' ; (hour(d)-1) % 12 + 1 # 12 時間表記での時
640
+ when 'j' ; yday(d) # 年の初めから通算の日数
641
+ when 'm' ; month(d) # 月
642
+ when 'M' ; minute(d) # 分
643
+ when 'p' ; (AMPM[hour(d).to_i.div(12)].translate(locale)).upcase # 現在のロケールにおける「午前」「午後」に相当する文字列
644
+ when 'P' ; (AMPM[hour(d).to_i.div(12)].translate(locale)).downcase # 前項を小文字で表記
645
+ when 's' ; universal_time / Duration::SECOND # 紀元 (1970-01-01T00:00:00Z) からの秒数
646
+ when 'S' ; second(d) # 秒 (10 進数表記)
647
+ when 'u' ; cwday # 週の何番目の日か(月曜日を 1 とする)
648
+ when 'U' ; yweek(6, 7, d) # 年の初めからの通算の週番号(日曜日始まり)
649
+ when 'V' ; cweek(d) # ISO 8601 形式での年の始めからの週番号
650
+ when 'w' ; wday # 週の何番目の日 か(日曜日を 0 とする)
651
+ when 'W' ; yweek(0, 7, d) # 年の初めからの通算の週番号(月曜日始まり)
652
+ when 'y' ; year(d) % 100 # 西暦の下2桁 (世紀部分を含まない年)
653
+ when 'Y' ; year(d) # 世紀部分を含めた ( 4 桁の) 西暦年
654
+ when 'z' ; clock.to_basic # +hhmm や -hhmm の形式のタイムゾーン
655
+ when 'Z' ; When::Parts::Locale.translate(clock.tzname[0],locale) # タイムゾーンまたはゾーン名または省略名
656
+ else ; designator
657
+ end
658
+ end
659
+
660
+ private
661
+
662
+ # 指定の書式による多言語対応文字列化
663
+ #
664
+ # @param [String] locale 文字列化を行う locale
665
+ # @param [When::BasicTypes::M17n] pattern 書式
666
+ #
667
+ # @return [Array] 書式と文字列化項目からなる配列
668
+ #
669
+ def _strftime(locale, pattern, t)
670
+ format, *terms = t
671
+ pattern = pattern.translate(locale) if pattern.kind_of?(When::BasicTypes::M17n)
672
+ pattern.scan(/(%[O\d]*(?:\.(\d+))?.)|(.)/) do |c,e,s|
673
+ case c
674
+ when /^%%/
675
+ format += '%%'
676
+ when /^%/
677
+ action = (TemporalPosition.format || Format)[c[-1..-1]]
678
+ case action
679
+ when Array
680
+ format += action[0]
681
+ terms << term(action[1], locale, c[1..-2].to_i, e||3)
682
+ when String
683
+ action = action.translate(locale) if action.kind_of?(When::BasicTypes::M17n)
684
+ if (action =~ /%/)
685
+ format, *terms = _strftime(locale, action, [format] + terms)
686
+ else
687
+ format += action
688
+ end
689
+ end
690
+ else
691
+ format += s
692
+ end
693
+ end
694
+ [format] + terms
695
+ end
696
+
697
+ #
698
+ # 使用する When::CalendarTypes::CalendarNote を決定する
699
+ #
700
+ # options に副作用があることに注意
701
+ #
702
+ def _calendar_note(options)
703
+ calendar_note = options.delete(:calendar_note) if options.kind_of?(Hash)
704
+ calendar_note ||= @frame ? @frame.note : 'JulianDayNotes'
705
+ When.CalendarNote(calendar_note)
706
+ end
707
+ end
708
+
709
+ class JulianDate
710
+
711
+ # 多言語対応文字列化 - ユリウス日を多言語対応文字列化する
712
+ #
713
+ # @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
714
+ #
715
+ # @return [When::BasicTypes::M17n]
716
+ #
717
+ def to_m17n(precision=@precision)
718
+ return m17n(to_s(precision))
719
+ end
720
+
721
+ # 文字列化 - ユリウス日を文字列化する
722
+ #
723
+ # @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
724
+ #
725
+ # @return [String]
726
+ #
727
+ def to_s(precision=@precision)
728
+ coordinate = (precision <= When::DAY) ? to_i : to_f
729
+ coordinate.to_s
730
+ end
731
+ end
732
+
733
+ class ClockTime
734
+
735
+ # 要素の多言語対応文字列化
736
+ #
737
+ # @param [Integer] index 多言語対応文字列化する要素の指定
738
+ # @param [When::BasicTypes::M17n] format 多言語対応文字列化の書式
739
+ #
740
+ # @return [When::BasicTypes::M17n]
741
+ #
742
+ def name(index, format=nil)
743
+ digit = _digit(index) {|digit| digit > DAY}
744
+ coordinate = @clk_time[digit]
745
+ return m17n(format % coordinate) if format
746
+
747
+ indices = @frame.indices[digit-1]
748
+ if indices
749
+ trunk = indices.trunk
750
+ branch = indices.branch
751
+ end
752
+ format = branch ? m17n("%02d:") : "%02d"
753
+ return m17n(format % coordinate) unless trunk
754
+ trunk = trunk[coordinate * 1]
755
+ return m17n(trunk) unless branch
756
+ return trunk.prefix(branch[coordinate * 0])
757
+ end
758
+
759
+ # 多言語対応文字列化 - When.exe Standard Representation により多言語対応文字列化する
760
+ #
761
+ # @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
762
+ #
763
+ # @return [When::BasicTypes::M17n]
764
+ #
765
+ def to_m17n(precision=@precision)
766
+ time = m17n('T' + _time_to_s(precision))
767
+ time += @frame.zone if (@frame && !@frame.equal?(Clock.local_time))
768
+ return time
769
+ end
770
+
771
+ # 文字列化 - When.exe Standard Representation により文字列化する
772
+ #
773
+ # @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
774
+ #
775
+ # @return [String]
776
+ #
777
+ def to_s(precision=@precision)
778
+ time = 'T' + _time_to_s(precision)
779
+ time += @frame.zone if (@frame && !@frame.equal?(Clock.local_time))
780
+ return time
781
+ end
782
+
783
+ # 時
784
+ #
785
+ # @param [Integer] d 時刻が'時分秒'でない表現のための桁位置変更指示(小さいほうに位置をずらす)
786
+ #
787
+ # @return [Numeric] 自身の「時」
788
+ #
789
+ def hour(d=0)
790
+ @clk_time[HOUR+d]
791
+ end
792
+
793
+ # 分
794
+ #
795
+ # @param [Integer] d 時刻が'時分秒'でない表現のための桁位置変更指示(小さいほうに位置をずらす)
796
+ #
797
+ #
798
+ # @return [Numeric] 自身の「分」
799
+ #
800
+ def minute(d=0)
801
+ @clk_time[MINUTE+d]
802
+ end
803
+ alias :min :minute
804
+
805
+ # 秒
806
+ #
807
+ # @param [Integer] d 時刻が'時分秒'でない表現のための桁位置変更指示(小さいほうに位置をずらす)
808
+ #
809
+ #
810
+ # @return [Numeric] 自身の「秒」
811
+ #
812
+ def second(d=0)
813
+ @clk_time[SECOND+d]
814
+ end
815
+ alias :sec :second
816
+
817
+ #protected
818
+ #
819
+ # 時間帯以外の部分の文字列化
820
+ #
821
+ # @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
822
+ #
823
+ # @return [String]
824
+ #
825
+ # @private
826
+ def _time_to_s(precision=@precision)
827
+ terms = []
828
+ format = ''
829
+ format += Pair::DL2[@clk_time[0] * 0] || ':' if @frame.pair[0] || @clk_time[0].kind_of?(Pair)
830
+
831
+ # 時分
832
+ digits = [@clk_time.length-2, precision].min
833
+ if digits > 0
834
+ terms += @clk_time[1..-1]
835
+ format += "%02d:" * digits
836
+ format = format[0..-2] if precision == digits
837
+ end
838
+
839
+ # 秒
840
+ digits = [precision - @clk_time.length + 1, STRING-SECOND].min
841
+ if digits >= 0
842
+ terms << @clk_time[-1]
843
+ format += (digits == 0) ? "%02d" : "%02.#{digits}f"
844
+ end
845
+
846
+ # 結果
847
+ time = Pair._format([format] + terms)
848
+ time.sub(/([^\d])(\d)\./, '\10\2.')
849
+ end
850
+
851
+ #
852
+ # to_hash のための要素生成
853
+ # @private
854
+ def _to_hash_value(options={})
855
+ clk_time.map {|e| _m17n_form(e, options) }
856
+ end
857
+ end
858
+
859
+ class CalDate
860
+
861
+ #
862
+ # 暦法名
863
+ #
864
+ # @return [Array] ( name, epoch, reverse, go back )
865
+ # - name 暦法または暦年代 ({When::TM::Calendar}, {When::TM::CalendarEra})
866
+ # - epoch 暦元 (Integer)
867
+ # - reverse 暦年の順序 (Boolean)
868
+ # [ false, nil 昇順 ]
869
+ # [ true 降順 ]
870
+ # - go back 参照イベントより前の暦日か(Boolean)
871
+ # [ false, nil 否 ]
872
+ # [ true 然り ]
873
+ #
874
+ def calendar_name
875
+ void, epoch, reverse, back = @calendar_era_name
876
+ name = [@calendar_era || @frame, epoch, reverse, back]
877
+ name.pop until name[-1]
878
+ return name
879
+ end
880
+
881
+ #
882
+ # 参照ラベル
883
+ #
884
+ # @return [When::BasicTypes::M17n]
885
+ #
886
+ def reference_label
887
+ return @calendar_era.hierarchy.map {|e| e.label} if @calendar_era
888
+ return [@frame.label] if @frame.label
889
+ [When::BasicTypes::M17n.new(@frame.class.to_s.split(/::/)[-1])]
890
+ end
891
+
892
+ #
893
+ # Hash 化
894
+ #
895
+ # @param [String] options { :notes => String } という Hash の指定と等価
896
+ # @param [Integer] options { :indices => Integer } という Hash の指定と等価
897
+ # @param [Hash] options 下記のとおり
898
+ # @option options [When::CalendarTypes::CalendarNote, String] :calendar_note 暦注を計算する暦注オブジェクトまたはそのIRI
899
+ # @option options [Object] その他のキー {When::CalendarTypes::CalendarNote#notes} を参照
900
+ #
901
+ # @return [Hash]
902
+ # - :calendar calendar_name の結果 ( name, epoch, reverse, go back )
903
+ # - name 暦法または暦年代 ({When::TM::Calendar}, {When::TM::CalendarEra})
904
+ # - epoch 暦元 (Integer)
905
+ # - reverse 暦年の順序 (Boolean)
906
+ # [ false, nil 昇順 ]
907
+ # [ true 降順 ]
908
+ # - go back 参照イベントより前の暦日か(Boolean)
909
+ # [ false, nil 否 ]
910
+ # [ true 然り ]
911
+ # - :cal_date cal_date の内容 (year, month, day)
912
+ # [ year - 年 ({Numeric}) ]
913
+ # [ month - 月 ({Numeric}) ]
914
+ # [ day - 日 ({Numeric}) ]
915
+ # - :clk_time to_clock_time の結果 ( 日, 時, 分, 秒 )
916
+ # - :notes Hash (の Array (の Array)) - _notes(options)
917
+ #
918
+ def _to_hash(options={})
919
+ super.update({:cal_date=>@cal_date})
920
+ end
921
+
922
+ # 要素の多言語対応文字列化
923
+ #
924
+ # @param [Integer] index 多言語対応文字列化する要素の指定
925
+ # @param [When::BasicTypes::M17n] format 多言語対応文字列化の書式
926
+ #
927
+ # @return [When::BasicTypes::M17n]
928
+ #
929
+ def name(index, format=nil)
930
+ digit = _digit(index) {|digit| digit <= DAY}
931
+ coordinate = @cal_date[digit-1]
932
+ return m17n(format % coordinate) if format
933
+
934
+ indices = @frame.indices[digit-1]
935
+ if indices
936
+ trunk = indices.trunk
937
+ branch = indices.branch
938
+ end
939
+ format = branch ? m17n("%02d-") : "%02d"
940
+ return m17n(format % coordinate) unless trunk
941
+ trunk = trunk[coordinate * 1]
942
+ return m17n(trunk) unless branch
943
+ return trunk.prefix(branch[coordinate * 0||0])
944
+ end
945
+
946
+ # 日
947
+ #
948
+ # @param [Integer] d 日付が'年月日'でない表現のための桁位置変更指示(大きいほうに位置をずらす)
949
+ #
950
+ # @return [Numeric] 自身の「日」
951
+ #
952
+ def day(d=0)
953
+ @cal_date[DAY-1-d]
954
+ end
955
+
956
+ # 月内通日
957
+ #
958
+ # @param [Integer] d 日付が'年月日'でない表現のための桁位置変更指示(大きいほうに位置をずらす)
959
+ #
960
+ # @return [Numeric] 自身の「月内通日」(1始まり)
961
+ #
962
+ def mday(d=0)
963
+ to_i - floor(MONTH-d).to_i + 1
964
+ end
965
+
966
+ # 年内通日
967
+ #
968
+ # @param [Integer] d 日付が'年月日'でない表現のための桁位置変更指示(大きいほうに位置をずらす)
969
+ #
970
+ # @return [Numeric] 自身の「年内通日」(1始まり)
971
+ #
972
+ def yday(d=0)
973
+ to_i - floor(YEAR-d).to_i + 1
974
+ end
975
+
976
+ # 七曜
977
+ #
978
+ # @return [Numeric] 自身の「七曜」(日曜 0 始まり)
979
+ #
980
+ def wday
981
+ (to_i + 1) % 7
982
+ end
983
+
984
+ # 七曜(暦週)
985
+ #
986
+ # @return [Numeric] 自身の「七曜」(月曜 1 始まり)
987
+ #
988
+ def cwday
989
+ (to_i % 7) + 1
990
+ end
991
+
992
+ # 暦週
993
+ #
994
+ # @param [Integer] d 日付が'年月日'でない表現のための桁位置変更指示(大きいほうに位置をずらす)
995
+ #
996
+ # @return [Numeric] 自身の「暦週」
997
+ #
998
+ def cweek(d=0)
999
+ [1,0,-1].each do |i|
1000
+ start = ((self + PeriodDuration.new(i, YEAR-d)).floor(YEAR-d,DAY) + PeriodDuration.new(4, DAY)) & Residue.new(0,7,-1)
1001
+ return ((to_i - start.to_i).div 7) + 1 if self >= start
1002
+ end
1003
+ raise IndexError, 'Cannot decide year number'
1004
+ end
1005
+
1006
+ # 月内通週
1007
+ #
1008
+ # @param [Integer] w 週の最初の曜日(0:月,.., 6:日)
1009
+ # @param [Integer] m 一週間の日数
1010
+ # @param [Integer] d 日付が'年月日'でない表現のための桁位置変更指示(大きいほうに位置をずらす)
1011
+ #
1012
+ # @return [Numeric] 自身の「月内通週」(その月に完全に含まれる最初の週を1とする)
1013
+ #
1014
+ def mweek(w=6, m=7, d=0)
1015
+ 1 + (to_i - (floor(MONTH-d,DAY) & Residue.new(w,m)).to_i).div(7)
1016
+ end
1017
+
1018
+ # 年内通週
1019
+ #
1020
+ # @param [Integer] w 週の最初の曜日(0:月,.., 6:日)
1021
+ # @param [Integer] m 一週間の日数
1022
+ # @param [Integer] d 日付が'年月日'でない表現のための桁位置変更指示(大きいほうに位置をずらす)
1023
+ #
1024
+ # @return [Numeric]
1025
+ # 自身の「年内通週」(その年に完全に含まれる最初の週を1とする)
1026
+ #
1027
+ def yweek(w=6, m=7, d=0)
1028
+ 1 + (to_i - (floor(YEAR-d,DAY) & Residue.new(w,m)).to_i).div(7)
1029
+ end
1030
+
1031
+ # 月
1032
+ #
1033
+ # @param [Integer] d 日付が'年月日'でない表現のための桁位置変更指示(大きいほうに位置をずらす)
1034
+ #
1035
+ # @return [Numeric] 自身の「月」
1036
+ #
1037
+ def month(d=0)
1038
+ @cal_date[MONTH-1-d]
1039
+ end
1040
+ alias :mon :month
1041
+
1042
+ # 年内通月
1043
+ #
1044
+ # @param [Integer] d1 日付が'年月日'でない表現のための桁位置変更指示-年用(大きいほうに位置をずらす)
1045
+ # @param [Integer] d2 日付が'年月日'でない表現のための桁位置変更指示-月用(大きいほうに位置をずらす)
1046
+ #
1047
+ # @return [Numeric] 自身の「年内通月」(1始まり)
1048
+ #
1049
+ def ymon(d1=0, d2=0)
1050
+ current = floor(YEAR-d1, MONTH-d2)
1051
+ @frame._length(@cal_date[(YEAR-1-d1)...(MONTH-1-d2)]).times do |i|
1052
+ return i+1 if current == self
1053
+ current = current.succ
1054
+ end
1055
+ raise IndexError, 'Cannot decide month number'
1056
+ end
1057
+
1058
+ # 年
1059
+ #
1060
+ # @param [Integer] d 日付が'年月日'でない表現のための桁位置変更指示(大きいほうに位置をずらす)
1061
+ #
1062
+ # @return [Numeric] 自身の「年」
1063
+ #
1064
+ def year(d=0)
1065
+ @cal_date[YEAR-1-d]
1066
+ end
1067
+
1068
+ # 暦週の年
1069
+ #
1070
+ # @param [Integer] d 日付が'年月日'でない表現のための桁位置変更指示(大きいほうに位置をずらす)
1071
+ #
1072
+ # @return [Numeric] 自身の「暦週の年」
1073
+ #
1074
+ def cwyear(d=0)
1075
+ [1,0,-1].each do |i|
1076
+ start = ((self + PeriodDuration.new(i, YEAR-d)).floor(YEAR-d,DAY) + PeriodDuration.new(4, DAY)) & Residue.new(0,7,-1)
1077
+ return year(d)+i if self >= start
1078
+ end
1079
+ raise IndexError, 'Cannot decide year number'
1080
+ end
1081
+
1082
+ # 多言語対応文字列化 - When.exe Standard Representation により多言語対応文字列化する
1083
+ #
1084
+ # @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
1085
+ #
1086
+ # @return [When::BasicTypes::M17n]
1087
+ #
1088
+ def to_m17n(precision=@precision)
1089
+ era, = @calendar_era_name
1090
+ date = _date_to_s(precision)
1091
+ return m17n(date) unless era
1092
+ return m17n(era) + date
1093
+ end
1094
+
1095
+ # 文字列化 - When.exe Standard Representation により文字列化する
1096
+ #
1097
+ # @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
1098
+ #
1099
+ # @return [String]
1100
+ #
1101
+ def to_s(precision=@precision)
1102
+ era, = @calendar_era_name
1103
+ date = _date_to_s(precision)
1104
+ return date unless era
1105
+ return era.to_s + date
1106
+ end
1107
+
1108
+ # event を 文字列化 - 日時で与えられた event を文字列化する
1109
+ #
1110
+ # @note
1111
+ # events 配列なし - 日時をそのまま文字列化
1112
+ # 日時の精度が日より細かい - イベント名(イベント時刻)
1113
+ # 日時の精度が日 - イベント名(当日までの経過日数)
1114
+ #
1115
+ def _event_form(other=nil)
1116
+ return to_m17n unless events
1117
+ return events[0] + '(' + clk_time.to_s[/[:*=0-9]+/] + ')' if precision > When::DAY
1118
+ return events[0] unless other
1119
+ other = JulianDate.dynamical_time(other.dynamical_time,
1120
+ {:time_standard=>time_standard}) unless rate_of_clock == other.rate_of_clock
1121
+ events[0] + '(' + (other.to_i - to_i).to_s + ')'
1122
+ end
1123
+
1124
+ # 日付の年号以外の部分を文字列化する
1125
+ #
1126
+ # @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
1127
+ #
1128
+ # @return [String]
1129
+ #
1130
+ def _date_to_s(precision)
1131
+ # 準備
1132
+ precision = [precision, 1 - @cal_date.length].max
1133
+ precision = [precision, DAY].min
1134
+ terms = []
1135
+ format = ""
1136
+
1137
+ # 年
1138
+ year_by_epoch = @cal_date[0]
1139
+ if (@calendar_era_name)
1140
+ era, epoch, reverse = @calendar_era_name
1141
+ year_in_term = reverse ? -year_by_epoch : year_by_epoch
1142
+ year_by_calendar = epoch + year_by_epoch if epoch
1143
+ terms << year_in_term
1144
+ format += (0..99) === (year_in_term * 1) ? "%02d." : "%04d."
1145
+ if year_by_calendar && year_by_calendar != year_in_term
1146
+ terms << (year_by_calendar * 1)
1147
+ format += "(%04d)"
1148
+ end
1149
+ else
1150
+ terms << year_by_epoch
1151
+ format += (0..9999) === (year_by_epoch * 1) ? "%04d." : "%06d."
1152
+ end
1153
+
1154
+ # 月日
1155
+ ((1-@cal_date.length)..-1).each do |i|
1156
+ break if (i >= precision)
1157
+ terms << @cal_date[i]
1158
+ format += "%02d."
1159
+ end
1160
+
1161
+ # 結果
1162
+ date = Pair._format([format] + terms)
1163
+ date.sub!(/([^\d])\(([-+\d]+)\)/, '(\2)\1') if era
1164
+ date = date[0..-2] unless @frame.pair[precision-1] || date[-1..-1] != '.'
1165
+ date.gsub!(/\./, '-') if (@frame.indices.length <= DefaultDateIndex.length) && !era
1166
+ return date
1167
+ end
1168
+ end
1169
+
1170
+ class DateAndTime < CalDate
1171
+
1172
+ # 要素の多言語対応文字列化
1173
+ #
1174
+ # @param [Integer] index 多言語対応文字列化する要素の指定
1175
+ # @param [When::BasicTypes::M17n] format 多言語対応文字列化の書式
1176
+ #
1177
+ # @return [When::BasicTypes::M17n]
1178
+ #
1179
+ def name(index, format=nil)
1180
+ digit = _digit(index)
1181
+ (digit <= DAY) ? super : @clk_time.name(digit, format)
1182
+ end
1183
+
1184
+ # 多言語対応文字列化 - When.exe Standard Representation により多言語対応文字列化する
1185
+ #
1186
+ # @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
1187
+ #
1188
+ # @return [When::BasicTypes::M17n]
1189
+ #
1190
+ def to_m17n(precision=@precision)
1191
+ super + @clk_time.to_m17n(precision)
1192
+ end
1193
+
1194
+ # 文字列化 -When.exe Standard Representation により文字列化する
1195
+ #
1196
+ # @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
1197
+ #
1198
+ # @return [String]
1199
+ #
1200
+ def to_s(precision=@precision)
1201
+ super + @clk_time.to_s(precision)
1202
+ end
1203
+
1204
+ # 時
1205
+ #
1206
+ # @param [Integer] d 時刻が'時分秒'でない表現のための桁位置変更指示(小さいほうに位置をずらす)
1207
+ #
1208
+ # @return [Numeric] 自身の「時」
1209
+ #
1210
+ def hour(d=0)
1211
+ @clk_time.hour(d)
1212
+ end
1213
+
1214
+ # 分
1215
+ #
1216
+ # @param [Integer] d 時刻が'時分秒'でない表現のための桁位置変更指示(小さいほうに位置をずらす)
1217
+ #
1218
+ # @return [Numeric] 自身の「分」
1219
+ #
1220
+ def minute(d=0)
1221
+ @clk_time.minute(d)
1222
+ end
1223
+ alias :min :minute
1224
+
1225
+ # 秒
1226
+ #
1227
+ # @param [Integer] d 時刻が'時分秒'でない表現のための桁位置変更指示(小さいほうに位置をずらす)
1228
+ #
1229
+ # @return [Numeric] 自身の「秒」
1230
+ #
1231
+ def second(d=0)
1232
+ @clk_time.second(d)
1233
+ end
1234
+ alias :sec :second
1235
+ end
1236
+ end
1237
+ end