when_exe 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +333 -212
- data/bin/make_ttl.rb +37 -0
- data/bin/make_ttl.rb.config +9 -0
- data/lib/when_exe.rb +923 -925
- data/lib/when_exe/calendarnote.rb +9 -5
- data/lib/when_exe/coordinates.rb +2437 -2446
- data/lib/when_exe/inspect.rb +1480 -1408
- data/lib/when_exe/linkeddata.rb +574 -0
- data/lib/when_exe/locales/akt.rb +177 -176
- data/lib/when_exe/locales/locale.rb +751 -751
- data/lib/when_exe/mini_application.rb +307 -307
- data/lib/when_exe/parts/resource.rb +1115 -1103
- data/lib/when_exe/region/chinese/epochs.rb +6 -5
- data/lib/when_exe/region/christian.rb +831 -829
- data/lib/when_exe/region/japanese.rb +93 -93
- data/lib/when_exe/region/japanese/notes.rb +1510 -1495
- data/lib/when_exe/region/japanese/residues.rb +13 -13
- data/lib/when_exe/tmposition.rb +2307 -2273
- data/lib/when_exe/tmreference.rb +1744 -1734
- data/lib/when_exe/version.rb +2 -2
- data/link_to_online_documents +1 -1
- data/test/scripts/3.ext.rb +6 -6
- data/test/scripts/3.rb +6 -6
- data/test/test.rb +76 -75
- data/test/test/icalendar.rb +883 -879
- data/test/test/linkeddata.rb +224 -0
- data/test/test/region/m17n.rb +193 -193
- data/when_exe.gemspec +3 -2
- metadata +13 -6
@@ -1,307 +1,307 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
=begin
|
3
|
-
Copyright (C) 2013-
|
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
|
-
require 'socket'
|
9
|
-
|
10
|
-
#
|
11
|
-
# Time for v1.8.x compatibility
|
12
|
-
#
|
13
|
-
class Time
|
14
|
-
if Time.now.respond_to?(:strftime) && Time.now.strftime('%FT%X.%L').length > 0
|
15
|
-
alias :_log_ :strftime
|
16
|
-
else
|
17
|
-
def _log_(format)
|
18
|
-
"%04d-%02d-%02dT%02d:%02d:%02d.%03d" % [year, month, day, hour, min, sec, usec / 1000]
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
#
|
24
|
-
# Micro Client / Server
|
25
|
-
#
|
26
|
-
module When
|
27
|
-
class << self
|
28
|
-
|
29
|
-
#
|
30
|
-
# 設定ファイルを読み込む
|
31
|
-
# @private
|
32
|
-
def config(path=File.expand_path($0) + '.config')
|
33
|
-
config = {}
|
34
|
-
open(path, 'r') do |file|
|
35
|
-
while (line=file.gets)
|
36
|
-
next if line =~ /\A\s*#/
|
37
|
-
key, *value = line.chomp.split(':')
|
38
|
-
value = value[0] if value.size <= 1
|
39
|
-
config[key] = value
|
40
|
-
end
|
41
|
-
end
|
42
|
-
config
|
43
|
-
rescue
|
44
|
-
{}
|
45
|
-
end
|
46
|
-
|
47
|
-
#
|
48
|
-
# マイクロ・サーバーを起動する
|
49
|
-
#
|
50
|
-
# @param [#to_i] port 待ち受けるポート番号
|
51
|
-
#
|
52
|
-
# @return [void]
|
53
|
-
#
|
54
|
-
# @note mini_application
|
55
|
-
#
|
56
|
-
def server(port)
|
57
|
-
config = When.config
|
58
|
-
TCPServer.open(port.to_i) do |socket|
|
59
|
-
puts Time.now._log_('%FT%X.%L') + ': Start'
|
60
|
-
loop do
|
61
|
-
Thread.start(socket.accept) do |client|
|
62
|
-
query = client.gets.chomp.force_encoding("UTF-8")
|
63
|
-
start = Time.now
|
64
|
-
puts start._log_('%FT%X.%L') + ': Query - ' + When::Locale.translate(query, config['!'])
|
65
|
-
begin
|
66
|
-
result = free_conv(*query.split(/\s+/))
|
67
|
-
result = When::Locale.translate(result, config['!'])
|
68
|
-
client.puts JSON.generate(Array(_to_string(result))).to_s
|
69
|
-
stop = Time.now
|
70
|
-
puts stop._log_('%FT%X.%L') + ": Respond (%7.0f ms)" % (1000 * (stop.to_f - start.to_f))
|
71
|
-
rescue => err
|
72
|
-
puts Time.now._log_('%FT%X.%L') + ': error - ' + err.to_s
|
73
|
-
client.puts JSON.generate({:error=>query}).to_s
|
74
|
-
end
|
75
|
-
client.close
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
rescue Exception => e
|
80
|
-
puts Time.now._log_('%FT%X.%L') + ': Exception - ' + e.to_s
|
81
|
-
ensure
|
82
|
-
puts Time.now._log_('%FT%X.%L') + ': Done.'
|
83
|
-
end
|
84
|
-
|
85
|
-
#
|
86
|
-
# マイクロ・クライアントを実行する
|
87
|
-
#
|
88
|
-
# @param [String] server マイクロ・サーバのアドレス
|
89
|
-
# @param [#to_i] port つなぐポート番号
|
90
|
-
# @param [String] query 問い合わせ文字列
|
91
|
-
#
|
92
|
-
# @return [JSON] 応答
|
93
|
-
#
|
94
|
-
# @note mini_application
|
95
|
-
#
|
96
|
-
def client(server, port, query)
|
97
|
-
TCPSocket.open(server, port.to_i) do |socket|
|
98
|
-
socket.puts(query)
|
99
|
-
results = JSON.parse(socket.gets.force_encoding("UTF-8"))
|
100
|
-
results = Hash[*results.flatten(1)] if results[0].kind_of?(Array)
|
101
|
-
_to_symbol(results)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# 日付の自由変換
|
106
|
-
#
|
107
|
-
# @param [Array<String, When::TM::TemporalPosition, When::TM::CalendarEra or When::TM::Calendar>] args コマンドライン入力
|
108
|
-
# @param [Block] block ブロック
|
109
|
-
#
|
110
|
-
# @return [Array<Hash>] 変換結果
|
111
|
-
# @return [Array<Array<Numeric>>] 最良近似分数列
|
112
|
-
#
|
113
|
-
# @note 暦法のIRI, When.exe Standard Expression, 最良近似分数列の分母分子などを文字列で指定
|
114
|
-
# @note mini_application
|
115
|
-
#
|
116
|
-
def free_conv(*args, &block)
|
117
|
-
calendars, dates, numbers, methods, output, options = _parse_command(args)
|
118
|
-
|
119
|
-
if numbers.size >= 2 && calendars.size == 0
|
120
|
-
result = []
|
121
|
-
When::Coordinates::Residue.new(numbers[0], numbers[1]).each { |v| result << v }
|
122
|
-
return result
|
123
|
-
end
|
124
|
-
|
125
|
-
block ||=
|
126
|
-
if methods.size == 0
|
127
|
-
lambda {|date| date.send(*output)}
|
128
|
-
else
|
129
|
-
lambda {|date, type| column(date, type)}
|
130
|
-
end
|
131
|
-
_free_conv(calendars, dates, methods, output, options, &block)
|
132
|
-
end
|
133
|
-
|
134
|
-
# 七曜表の一日分
|
135
|
-
#
|
136
|
-
# @param [When::TM::TemporalPosition] date 処理する一日
|
137
|
-
# @param [Integer, nil] type 当該日の種類
|
138
|
-
#
|
139
|
-
# @return [Object>] 処理結果
|
140
|
-
#
|
141
|
-
def column(date, type)
|
142
|
-
case type
|
143
|
-
when When::YEAR ; date.strftime("%Y")
|
144
|
-
when When::MONTH ; date.strftime("%B %Y")
|
145
|
-
when When::WEEK ; nil
|
146
|
-
when When::DAY ; date[0]
|
147
|
-
else ; '-'
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
private
|
152
|
-
|
153
|
-
# to_h メソッドのオプション設定
|
154
|
-
HashMethod = {:iri => [:to_h, {:method=>:iri , :prefix=>true}],
|
155
|
-
:to_m17n => [:to_h, {:method=>:to_m17n, :prefix=>true}]}
|
156
|
-
|
157
|
-
# 引数読み込み
|
158
|
-
#
|
159
|
-
# args [String] コマンドライン入力
|
160
|
-
#
|
161
|
-
# @return [Array] ( calendars, dates, numbers, methods )
|
162
|
-
# [ calendars [Array<When::TM::Calendar or When::TM::CalendarEra>]]
|
163
|
-
# [ dates [Array<When::TM::CalData or When::TM::DateAndTime>] ]
|
164
|
-
# [ numbers [Array<Numeric>]]
|
165
|
-
# [ methods [Array<String>] メソッド名('week', 'month', 'year') ]
|
166
|
-
# [ output [Array<Symbol, String>] 出力処理に使うメソッドのシンボルと引数 ]
|
167
|
-
# [ options [Hash{ :extent=>Boolean, :go_back=><:All || :Before(nil) || :After> }]
|
168
|
-
#
|
169
|
-
def _parse_command(args)
|
170
|
-
calendars = []
|
171
|
-
dates = []
|
172
|
-
numbers = []
|
173
|
-
methods = []
|
174
|
-
options = {}
|
175
|
-
output = [:to_s]
|
176
|
-
|
177
|
-
config = When.config
|
178
|
-
args.flatten.each do |arg|
|
179
|
-
case arg
|
180
|
-
when Numeric ; dates << arg ; numbers << arg
|
181
|
-
when Hash ; options.update(arg)
|
182
|
-
when Range ; arg.each {|d| dates << d}
|
183
|
-
when Symbol ; output = [arg]
|
184
|
-
when When::TM::CalendarEra,
|
185
|
-
When::TM::Calendar ; calendars << arg
|
186
|
-
when String
|
187
|
-
arg = When::EncodingConversion.to_internal_encoding(arg)
|
188
|
-
case arg
|
189
|
-
when /\A:(.+?)(?:\[(..)\])?\z/ ; output = [$1.to_sym, $2].compact
|
190
|
-
when /\A(year|month|week)(?:\[(..)\])?\z/i ; methods << [$1.downcase + '_included', $2||'SU']
|
191
|
-
when /\A[-+\d]\d*\z/ ; dates << arg.to_i ; numbers << arg.to_i
|
192
|
-
when /\A[-+.\d][.\d]*\z/ ; dates << arg.to_f ; numbers << arg.to_f
|
193
|
-
when /\Anow\z/i ; dates << When.now
|
194
|
-
when /\Atoday\z/i ; dates << When.today
|
195
|
-
when /(^[-+\d])|\^/ ; dates << arg
|
196
|
-
when /\A\//
|
197
|
-
arg[1..-1].scan(/./) do |c|
|
198
|
-
c = c.upcase
|
199
|
-
if config.key?(c)
|
200
|
-
calendar = config[c]
|
201
|
-
calendar = calendar.join(':') if calendar.kind_of?(Array)
|
202
|
-
calendars << When.Calendar(calendar)
|
203
|
-
elsif c == 'D'
|
204
|
-
calendars << When::TM::JulianDate
|
205
|
-
end
|
206
|
-
end
|
207
|
-
else
|
208
|
-
begin
|
209
|
-
calendars << ((arg == 'JulianDate') ? When::TM::JulianDate : When.Calendar(arg))
|
210
|
-
rescue NameError, OpenURI::HTTPError
|
211
|
-
dates << arg
|
212
|
-
end
|
213
|
-
end
|
214
|
-
else
|
215
|
-
dates << arg
|
216
|
-
end
|
217
|
-
end
|
218
|
-
[calendars, dates, numbers, methods, HashMethod[output[0]] || output, options]
|
219
|
-
end
|
220
|
-
|
221
|
-
# 変換処理(実行部)
|
222
|
-
#
|
223
|
-
# @param [When::TM::Calendar, When::TM::CalendarEra] calendars
|
224
|
-
# @param [When::TM::CalData, When::TM::DateAndTime] dates
|
225
|
-
# @param [String] methods メソッド名('week', 'month', 'year')
|
226
|
-
# @param [Hash] options {:extent=>Boolean, :go_back=><:All||:Before(nil)||:After>}
|
227
|
-
#
|
228
|
-
# @return [Array] 変換結果
|
229
|
-
#
|
230
|
-
def _free_conv(calendars, dates, methods, output, options, &block)
|
231
|
-
dates[0] ||= When.now
|
232
|
-
calendars[0] ||= When::Gregorian
|
233
|
-
result = dates.map {|date|
|
234
|
-
date = When.when?(date)
|
235
|
-
opts = {}
|
236
|
-
opts[:location] = date.location if date.location
|
237
|
-
opts[:clock ] = date.clock if date.respond_to?(:clock) && date.clock
|
238
|
-
list = calendars.dup
|
239
|
-
(0...calendars.size).to_a.reverse.each do |i|
|
240
|
-
case list[i]
|
241
|
-
when When::TM::Calendar ; list.slice!(i) if options[:extent] && !list[i].domain[''].include?(date)
|
242
|
-
when Class ;
|
243
|
-
else
|
244
|
-
eras = (date ^ list[i]).delete_if {|e| !e.leaf?}
|
245
|
-
unless options[:go_back] == :All
|
246
|
-
if options[:go_back] == :After
|
247
|
-
eras = [eras[(eras.index {|e| e.
|
248
|
-
else
|
249
|
-
eras.delete_if {|e| e.
|
250
|
-
end
|
251
|
-
end
|
252
|
-
list[i,1] = eras.map {|e| e.calendar_era}
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
if methods.size == 0
|
257
|
-
list.map {|calendar|
|
258
|
-
calendar.kind_of?(Class) ?
|
259
|
-
yield(calendar.new(date, opts.dup)) :
|
260
|
-
yield(calendar.^(calendar.rate_of_clock == date.time_standard.rate_of_clock ? date.to_i : date, opts))
|
261
|
-
}
|
262
|
-
else
|
263
|
-
list.map {|calendar|
|
264
|
-
date_for_calendar = calendar.^(calendar.rate_of_clock == date.time_standard.rate_of_clock ? date.to_i : date, opts)
|
265
|
-
methods.map {|method|
|
266
|
-
date_for_calendar.send(method[0].to_sym, method[1], &block)
|
267
|
-
}
|
268
|
-
}
|
269
|
-
end
|
270
|
-
}
|
271
|
-
result = result[0] while result.kind_of?(Array) && result.size == 1
|
272
|
-
return result
|
273
|
-
end
|
274
|
-
|
275
|
-
# JSONで通信するために Symbol を String に変換する
|
276
|
-
def _to_string(source)
|
277
|
-
case source
|
278
|
-
when Array
|
279
|
-
source.map {|e| _to_string(e)}
|
280
|
-
when Hash
|
281
|
-
result = {}
|
282
|
-
source.each_pair {|k,v|
|
283
|
-
result[k.kind_of?(Symbol) ? '_sym_' + k.to_s : k] = _to_string(v)
|
284
|
-
}
|
285
|
-
result
|
286
|
-
else
|
287
|
-
source
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
# JSONで通信するために String を Symbol に変換する
|
292
|
-
def _to_symbol(source)
|
293
|
-
case source
|
294
|
-
when Array
|
295
|
-
source.map {|e| _to_symbol(e)}
|
296
|
-
when Hash
|
297
|
-
result = {}
|
298
|
-
source.each_pair {|k,v|
|
299
|
-
result[k =~ /\A_sym_(.+)\z/ ? $1.to_sym : k] = _to_symbol(v)
|
300
|
-
}
|
301
|
-
result
|
302
|
-
else
|
303
|
-
source
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end
|
307
|
-
end
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
=begin
|
3
|
+
Copyright (C) 2013-2015 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
|
+
require 'socket'
|
9
|
+
|
10
|
+
#
|
11
|
+
# Time for v1.8.x compatibility
|
12
|
+
#
|
13
|
+
class Time
|
14
|
+
if Time.now.respond_to?(:strftime) && Time.now.strftime('%FT%X.%L').length > 0
|
15
|
+
alias :_log_ :strftime
|
16
|
+
else
|
17
|
+
def _log_(format)
|
18
|
+
"%04d-%02d-%02dT%02d:%02d:%02d.%03d" % [year, month, day, hour, min, sec, usec / 1000]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Micro Client / Server
|
25
|
+
#
|
26
|
+
module When
|
27
|
+
class << self
|
28
|
+
|
29
|
+
#
|
30
|
+
# 設定ファイルを読み込む
|
31
|
+
# @private
|
32
|
+
def config(path=File.expand_path($0) + '.config')
|
33
|
+
config = {}
|
34
|
+
open(path, 'r') do |file|
|
35
|
+
while (line=file.gets)
|
36
|
+
next if line =~ /\A\s*#/
|
37
|
+
key, *value = line.chomp.split(':')
|
38
|
+
value = value[0] if value.size <= 1
|
39
|
+
config[key] = value
|
40
|
+
end
|
41
|
+
end
|
42
|
+
config
|
43
|
+
rescue
|
44
|
+
{}
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# マイクロ・サーバーを起動する
|
49
|
+
#
|
50
|
+
# @param [#to_i] port 待ち受けるポート番号
|
51
|
+
#
|
52
|
+
# @return [void]
|
53
|
+
#
|
54
|
+
# @note mini_application
|
55
|
+
#
|
56
|
+
def server(port)
|
57
|
+
config = When.config
|
58
|
+
TCPServer.open(port.to_i) do |socket|
|
59
|
+
puts Time.now._log_('%FT%X.%L') + ': Start'
|
60
|
+
loop do
|
61
|
+
Thread.start(socket.accept) do |client|
|
62
|
+
query = client.gets.chomp.force_encoding("UTF-8")
|
63
|
+
start = Time.now
|
64
|
+
puts start._log_('%FT%X.%L') + ': Query - ' + When::Locale.translate(query, config['!'])
|
65
|
+
begin
|
66
|
+
result = free_conv(*query.split(/\s+/))
|
67
|
+
result = When::Locale.translate(result, config['!'])
|
68
|
+
client.puts JSON.generate(Array(_to_string(result))).to_s
|
69
|
+
stop = Time.now
|
70
|
+
puts stop._log_('%FT%X.%L') + ": Respond (%7.0f ms)" % (1000 * (stop.to_f - start.to_f))
|
71
|
+
rescue => err
|
72
|
+
puts Time.now._log_('%FT%X.%L') + ': error - ' + err.to_s
|
73
|
+
client.puts JSON.generate({:error=>query}).to_s
|
74
|
+
end
|
75
|
+
client.close
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
rescue Exception => e
|
80
|
+
puts Time.now._log_('%FT%X.%L') + ': Exception - ' + e.to_s
|
81
|
+
ensure
|
82
|
+
puts Time.now._log_('%FT%X.%L') + ': Done.'
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# マイクロ・クライアントを実行する
|
87
|
+
#
|
88
|
+
# @param [String] server マイクロ・サーバのアドレス
|
89
|
+
# @param [#to_i] port つなぐポート番号
|
90
|
+
# @param [String] query 問い合わせ文字列
|
91
|
+
#
|
92
|
+
# @return [JSON] 応答
|
93
|
+
#
|
94
|
+
# @note mini_application
|
95
|
+
#
|
96
|
+
def client(server, port, query)
|
97
|
+
TCPSocket.open(server, port.to_i) do |socket|
|
98
|
+
socket.puts(query)
|
99
|
+
results = JSON.parse(socket.gets.force_encoding("UTF-8"))
|
100
|
+
results = Hash[*results.flatten(1)] if results[0].kind_of?(Array)
|
101
|
+
_to_symbol(results)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# 日付の自由変換
|
106
|
+
#
|
107
|
+
# @param [Array<String, When::TM::TemporalPosition, When::TM::CalendarEra or When::TM::Calendar>] args コマンドライン入力
|
108
|
+
# @param [Block] block ブロック
|
109
|
+
#
|
110
|
+
# @return [Array<Hash>] 変換結果
|
111
|
+
# @return [Array<Array<Numeric>>] 最良近似分数列
|
112
|
+
#
|
113
|
+
# @note 暦法のIRI, When.exe Standard Expression, 最良近似分数列の分母分子などを文字列で指定
|
114
|
+
# @note mini_application
|
115
|
+
#
|
116
|
+
def free_conv(*args, &block)
|
117
|
+
calendars, dates, numbers, methods, output, options = _parse_command(args)
|
118
|
+
|
119
|
+
if numbers.size >= 2 && calendars.size == 0
|
120
|
+
result = []
|
121
|
+
When::Coordinates::Residue.new(numbers[0], numbers[1]).each { |v| result << v }
|
122
|
+
return result
|
123
|
+
end
|
124
|
+
|
125
|
+
block ||=
|
126
|
+
if methods.size == 0
|
127
|
+
lambda {|date| date.send(*output)}
|
128
|
+
else
|
129
|
+
lambda {|date, type| column(date, type)}
|
130
|
+
end
|
131
|
+
_free_conv(calendars, dates, methods, output, options, &block)
|
132
|
+
end
|
133
|
+
|
134
|
+
# 七曜表の一日分
|
135
|
+
#
|
136
|
+
# @param [When::TM::TemporalPosition] date 処理する一日
|
137
|
+
# @param [Integer, nil] type 当該日の種類
|
138
|
+
#
|
139
|
+
# @return [Object>] 処理結果
|
140
|
+
#
|
141
|
+
def column(date, type)
|
142
|
+
case type
|
143
|
+
when When::YEAR ; date.strftime("%Y")
|
144
|
+
when When::MONTH ; date.strftime("%B %Y")
|
145
|
+
when When::WEEK ; nil
|
146
|
+
when When::DAY ; date[0]
|
147
|
+
else ; '-'
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
# to_h メソッドのオプション設定
|
154
|
+
HashMethod = {:iri => [:to_h, {:method=>:iri , :prefix=>true}],
|
155
|
+
:to_m17n => [:to_h, {:method=>:to_m17n, :prefix=>true}]}
|
156
|
+
|
157
|
+
# 引数読み込み
|
158
|
+
#
|
159
|
+
# args [String] コマンドライン入力
|
160
|
+
#
|
161
|
+
# @return [Array] ( calendars, dates, numbers, methods )
|
162
|
+
# [ calendars [Array<When::TM::Calendar or When::TM::CalendarEra>]]
|
163
|
+
# [ dates [Array<When::TM::CalData or When::TM::DateAndTime>] ]
|
164
|
+
# [ numbers [Array<Numeric>]]
|
165
|
+
# [ methods [Array<String>] メソッド名('week', 'month', 'year') ]
|
166
|
+
# [ output [Array<Symbol, String>] 出力処理に使うメソッドのシンボルと引数 ]
|
167
|
+
# [ options [Hash{ :extent=>Boolean, :go_back=><:All || :Before(nil) || :After> }]
|
168
|
+
#
|
169
|
+
def _parse_command(args)
|
170
|
+
calendars = []
|
171
|
+
dates = []
|
172
|
+
numbers = []
|
173
|
+
methods = []
|
174
|
+
options = {}
|
175
|
+
output = [:to_s]
|
176
|
+
|
177
|
+
config = When.config
|
178
|
+
args.flatten.each do |arg|
|
179
|
+
case arg
|
180
|
+
when Numeric ; dates << arg ; numbers << arg
|
181
|
+
when Hash ; options.update(arg)
|
182
|
+
when Range ; arg.each {|d| dates << d}
|
183
|
+
when Symbol ; output = [arg]
|
184
|
+
when When::TM::CalendarEra,
|
185
|
+
When::TM::Calendar ; calendars << arg
|
186
|
+
when String
|
187
|
+
arg = When::EncodingConversion.to_internal_encoding(arg)
|
188
|
+
case arg
|
189
|
+
when /\A:(.+?)(?:\[(..)\])?\z/ ; output = [$1.to_sym, $2].compact
|
190
|
+
when /\A(year|month|week)(?:\[(..)\])?\z/i ; methods << [$1.downcase + '_included', $2||'SU']
|
191
|
+
when /\A[-+\d]\d*\z/ ; dates << arg.to_i ; numbers << arg.to_i
|
192
|
+
when /\A[-+.\d][.\d]*\z/ ; dates << arg.to_f ; numbers << arg.to_f
|
193
|
+
when /\Anow\z/i ; dates << When.now
|
194
|
+
when /\Atoday\z/i ; dates << When.today
|
195
|
+
when /(^[-+\d])|\^/ ; dates << arg
|
196
|
+
when /\A\//
|
197
|
+
arg[1..-1].scan(/./) do |c|
|
198
|
+
c = c.upcase
|
199
|
+
if config.key?(c)
|
200
|
+
calendar = config[c]
|
201
|
+
calendar = calendar.join(':') if calendar.kind_of?(Array)
|
202
|
+
calendars << When.Calendar(calendar)
|
203
|
+
elsif c == 'D'
|
204
|
+
calendars << When::TM::JulianDate
|
205
|
+
end
|
206
|
+
end
|
207
|
+
else
|
208
|
+
begin
|
209
|
+
calendars << ((arg == 'JulianDate') ? When::TM::JulianDate : When.Calendar(arg))
|
210
|
+
rescue NameError, OpenURI::HTTPError
|
211
|
+
dates << arg
|
212
|
+
end
|
213
|
+
end
|
214
|
+
else
|
215
|
+
dates << arg
|
216
|
+
end
|
217
|
+
end
|
218
|
+
[calendars, dates, numbers, methods, HashMethod[output[0]] || output, options]
|
219
|
+
end
|
220
|
+
|
221
|
+
# 変換処理(実行部)
|
222
|
+
#
|
223
|
+
# @param [When::TM::Calendar, When::TM::CalendarEra] calendars
|
224
|
+
# @param [When::TM::CalData, When::TM::DateAndTime] dates
|
225
|
+
# @param [String] methods メソッド名('week', 'month', 'year')
|
226
|
+
# @param [Hash] options {:extent=>Boolean, :go_back=><:All||:Before(nil)||:After>}
|
227
|
+
#
|
228
|
+
# @return [Array] 変換結果
|
229
|
+
#
|
230
|
+
def _free_conv(calendars, dates, methods, output, options, &block)
|
231
|
+
dates[0] ||= When.now
|
232
|
+
calendars[0] ||= When::Gregorian
|
233
|
+
result = dates.map {|date|
|
234
|
+
date = When.when?(date)
|
235
|
+
opts = {}
|
236
|
+
opts[:location] = date.location if date.location
|
237
|
+
opts[:clock ] = date.clock if date.respond_to?(:clock) && date.clock
|
238
|
+
list = calendars.dup
|
239
|
+
(0...calendars.size).to_a.reverse.each do |i|
|
240
|
+
case list[i]
|
241
|
+
when When::TM::Calendar ; list.slice!(i) if options[:extent] && !list[i].domain[''].include?(date)
|
242
|
+
when Class ;
|
243
|
+
else
|
244
|
+
eras = (date ^ list[i]).delete_if {|e| !e.leaf?}
|
245
|
+
unless options[:go_back] == :All
|
246
|
+
if options[:go_back] == :After
|
247
|
+
eras = [eras[(eras.index {|e| e.calendar_era_go_back}) || -1]]
|
248
|
+
else
|
249
|
+
eras.delete_if {|e| e.calendar_era_go_back}
|
250
|
+
end
|
251
|
+
end
|
252
|
+
list[i,1] = eras.map {|e| e.calendar_era}
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
if methods.size == 0
|
257
|
+
list.map {|calendar|
|
258
|
+
calendar.kind_of?(Class) ?
|
259
|
+
yield(calendar.new(date, opts.dup)) :
|
260
|
+
yield(calendar.^(calendar.rate_of_clock == date.time_standard.rate_of_clock ? date.to_i : date, opts))
|
261
|
+
}
|
262
|
+
else
|
263
|
+
list.map {|calendar|
|
264
|
+
date_for_calendar = calendar.^(calendar.rate_of_clock == date.time_standard.rate_of_clock ? date.to_i : date, opts)
|
265
|
+
methods.map {|method|
|
266
|
+
date_for_calendar.send(method[0].to_sym, method[1], &block)
|
267
|
+
}
|
268
|
+
}
|
269
|
+
end
|
270
|
+
}
|
271
|
+
result = result[0] while result.kind_of?(Array) && result.size == 1
|
272
|
+
return result
|
273
|
+
end
|
274
|
+
|
275
|
+
# JSONで通信するために Symbol を String に変換する
|
276
|
+
def _to_string(source)
|
277
|
+
case source
|
278
|
+
when Array
|
279
|
+
source.map {|e| _to_string(e)}
|
280
|
+
when Hash
|
281
|
+
result = {}
|
282
|
+
source.each_pair {|k,v|
|
283
|
+
result[k.kind_of?(Symbol) ? '_sym_' + k.to_s : k] = _to_string(v)
|
284
|
+
}
|
285
|
+
result
|
286
|
+
else
|
287
|
+
source
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# JSONで通信するために String を Symbol に変換する
|
292
|
+
def _to_symbol(source)
|
293
|
+
case source
|
294
|
+
when Array
|
295
|
+
source.map {|e| _to_symbol(e)}
|
296
|
+
when Hash
|
297
|
+
result = {}
|
298
|
+
source.each_pair {|k,v|
|
299
|
+
result[k =~ /\A_sym_(.+)\z/ ? $1.to_sym : k] = _to_symbol(v)
|
300
|
+
}
|
301
|
+
result
|
302
|
+
else
|
303
|
+
source
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|