when_exe 0.2.100 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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