sisimai 4.16.0-java → 4.17.0-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sisimai might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/ANALYTICAL-PRECISION +7 -7
- data/Changes +15 -0
- data/Makefile +1 -1
- data/README.md +30 -28
- data/lib/sisimai.rb +20 -1
- data/lib/sisimai/address.rb +28 -9
- data/lib/sisimai/arf.rb +37 -46
- data/lib/sisimai/data.rb +67 -43
- data/lib/sisimai/datetime.rb +210 -210
- data/lib/sisimai/mda.rb +30 -30
- data/lib/sisimai/message.rb +3 -5
- data/lib/sisimai/msp/de/einsundeins.rb +14 -42
- data/lib/sisimai/msp/de/gmx.rb +17 -44
- data/lib/sisimai/msp/jp/biglobe.rb +15 -44
- data/lib/sisimai/msp/jp/ezweb.rb +20 -50
- data/lib/sisimai/msp/jp/kddi.rb +16 -43
- data/lib/sisimai/msp/ru/mailru.rb +20 -48
- data/lib/sisimai/msp/ru/yandex.rb +16 -50
- data/lib/sisimai/msp/uk/messagelabs.rb +17 -51
- data/lib/sisimai/msp/us/amazonses.rb +18 -40
- data/lib/sisimai/msp/us/amazonworkmail.rb +17 -35
- data/lib/sisimai/msp/us/aol.rb +17 -41
- data/lib/sisimai/msp/us/bigfoot.rb +15 -48
- data/lib/sisimai/msp/us/facebook.rb +63 -90
- data/lib/sisimai/msp/us/google.rb +15 -44
- data/lib/sisimai/msp/us/office365.rb +21 -46
- data/lib/sisimai/msp/us/outlook.rb +17 -50
- data/lib/sisimai/msp/us/receivingses.rb +20 -43
- data/lib/sisimai/msp/us/sendgrid.rb +13 -37
- data/lib/sisimai/msp/us/verizon.rb +30 -74
- data/lib/sisimai/msp/us/yahoo.rb +12 -40
- data/lib/sisimai/msp/us/zoho.rb +14 -42
- data/lib/sisimai/mta/activehunter.rb +11 -40
- data/lib/sisimai/mta/apachejames.rb +18 -40
- data/lib/sisimai/mta/courier.rb +20 -57
- data/lib/sisimai/mta/domino.rb +24 -56
- data/lib/sisimai/mta/exchange.rb +26 -54
- data/lib/sisimai/mta/exim.rb +20 -39
- data/lib/sisimai/mta/imailserver.rb +26 -71
- data/lib/sisimai/mta/interscanmss.rb +26 -44
- data/lib/sisimai/mta/mailfoundry.rb +12 -42
- data/lib/sisimai/mta/mailmarshalsmtp.rb +13 -43
- data/lib/sisimai/mta/mcafee.rb +17 -46
- data/lib/sisimai/mta/messagingserver.rb +14 -47
- data/lib/sisimai/mta/mfilter.rb +12 -35
- data/lib/sisimai/mta/mxlogic.rb +18 -42
- data/lib/sisimai/mta/notes.rb +22 -45
- data/lib/sisimai/mta/opensmtpd.rb +18 -48
- data/lib/sisimai/mta/postfix.rb +15 -45
- data/lib/sisimai/mta/qmail.rb +32 -60
- data/lib/sisimai/mta/sendmail.rb +13 -38
- data/lib/sisimai/mta/surfcontrol.rb +15 -44
- data/lib/sisimai/mta/userdefined.rb +14 -30
- data/lib/sisimai/mta/v5sendmail.rb +18 -40
- data/lib/sisimai/mta/x1.rb +12 -41
- data/lib/sisimai/mta/x2.rb +12 -41
- data/lib/sisimai/mta/x3.rb +12 -39
- data/lib/sisimai/mta/x4.rb +33 -66
- data/lib/sisimai/mta/x5.rb +15 -42
- data/lib/sisimai/reason.rb +8 -71
- data/lib/sisimai/reason/blocked.rb +3 -0
- data/lib/sisimai/reason/contenterror.rb +3 -0
- data/lib/sisimai/reason/delivered.rb +27 -0
- data/lib/sisimai/reason/exceedlimit.rb +3 -0
- data/lib/sisimai/reason/expired.rb +3 -0
- data/lib/sisimai/reason/feedback.rb +18 -0
- data/lib/sisimai/reason/filtered.rb +4 -0
- data/lib/sisimai/reason/hasmoved.rb +3 -0
- data/lib/sisimai/reason/hostunknown.rb +3 -0
- data/lib/sisimai/reason/mailboxfull.rb +3 -0
- data/lib/sisimai/reason/mailererror.rb +3 -0
- data/lib/sisimai/reason/mesgtoobig.rb +3 -0
- data/lib/sisimai/reason/networkerror.rb +3 -0
- data/lib/sisimai/reason/norelaying.rb +3 -0
- data/lib/sisimai/reason/notaccept.rb +3 -0
- data/lib/sisimai/reason/onhold.rb +3 -0
- data/lib/sisimai/reason/rejected.rb +3 -0
- data/lib/sisimai/reason/securityerror.rb +3 -0
- data/lib/sisimai/reason/spamdetected.rb +3 -0
- data/lib/sisimai/reason/suspend.rb +3 -0
- data/lib/sisimai/reason/syntaxerror.rb +41 -0
- data/lib/sisimai/reason/systemerror.rb +3 -0
- data/lib/sisimai/reason/systemfull.rb +3 -0
- data/lib/sisimai/reason/toomanyconn.rb +3 -0
- data/lib/sisimai/reason/undefined.rb +18 -0
- data/lib/sisimai/reason/userunknown.rb +3 -0
- data/lib/sisimai/reason/vacation.rb +18 -0
- data/lib/sisimai/rfc3464.rb +15 -40
- data/lib/sisimai/rfc3834.rb +1 -10
- data/lib/sisimai/rfc5322.rb +57 -19
- data/lib/sisimai/rhost/googleapps.rb +82 -82
- data/lib/sisimai/smtp/reply.rb +2 -1
- data/lib/sisimai/smtp/status.rb +154 -152
- data/lib/sisimai/string.rb +2 -3
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/maildir/bsd/rfc3464-29.eml +60 -0
- data/set-of-emails/maildir/bsd/us-amazonworkmail-06.eml +156 -0
- data/set-of-emails/maildir/bsd/us-amazonworkmail-07.eml +158 -0
- data/set-of-emails/maildir/bsd/us-google-15.eml +97 -0
- data/set-of-emails/maildir/bsd/us-google-16.eml +99 -0
- data/set-of-emails/maildir/bsd/us-google-17.eml +104 -0
- data/set-of-emails/maildir/dos/apachejames-01.eml +4 -4
- data/set-of-emails/maildir/dos/us-amazonworkmail-01.eml +156 -0
- data/set-of-emails/maildir/dos/us-office365-01.eml +102 -0
- data/set-of-emails/maildir/mac/apachejames-01.eml +1 -9
- data/set-of-emails/maildir/mac/us-amazonworkmail-01.eml +1 -7
- data/set-of-emails/maildir/mac/us-office365-01.eml +1 -4
- metadata +17 -2
data/lib/sisimai/data.rb
CHANGED
@@ -41,10 +41,10 @@ module Sisimai
|
|
41
41
|
|
42
42
|
EndOfEmail = Sisimai::String.EOM
|
43
43
|
RetryIndex = Sisimai::Reason.retry
|
44
|
-
RFC822Head = Sisimai::RFC5322.HEADERFIELDS(
|
44
|
+
RFC822Head = Sisimai::RFC5322.HEADERFIELDS(:all)
|
45
45
|
AddrHeader = {
|
46
|
-
|
47
|
-
|
46
|
+
addresser: RFC822Head[:addresser],
|
47
|
+
recipient: RFC822Head[:recipient],
|
48
48
|
}
|
49
49
|
|
50
50
|
# Constructor of Sisimai::Data
|
@@ -56,34 +56,26 @@ module Sisimai
|
|
56
56
|
# Create email address object
|
57
57
|
x0 = Sisimai::Address.parse([argvs['addresser']])
|
58
58
|
y0 = Sisimai::Address.parse([argvs['recipient']])
|
59
|
-
v0 = nil
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
if v0.is_a? Sisimai::Address
|
64
|
-
thing['addresser'] = v0
|
65
|
-
thing['senderdomain'] = v0.host
|
66
|
-
end
|
67
|
-
end
|
60
|
+
return nil unless x0.is_a? Array
|
61
|
+
return nil unless y0.is_a? Array
|
68
62
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
return nil if thing['recipient'].void
|
80
|
-
return nil if thing['addresser'].void
|
63
|
+
thing[:addresser] = Sisimai::Address.new(x0.shift)
|
64
|
+
return nil unless thing[:addresser].is_a? Sisimai::Address
|
65
|
+
return nil if thing[:addresser].void
|
66
|
+
thing[:senderdomain] = thing[:addresser].host
|
67
|
+
|
68
|
+
thing[:recipient] = Sisimai::Address.new(y0.shift)
|
69
|
+
return nil unless thing[:recipient].is_a? Sisimai::Address
|
70
|
+
return nil if thing[:recipient].void
|
71
|
+
thing[:destination] = thing[:recipient].host
|
72
|
+
thing[:alias] = argvs['alias'] || ''
|
81
73
|
|
82
|
-
@addresser = thing[
|
83
|
-
@senderdomain = thing[
|
84
|
-
@recipient = thing[
|
85
|
-
@destination = thing[
|
86
|
-
@alias = thing[
|
74
|
+
@addresser = thing[:addresser]
|
75
|
+
@senderdomain = thing[:senderdomain]
|
76
|
+
@recipient = thing[:recipient]
|
77
|
+
@destination = thing[:destination]
|
78
|
+
@alias = thing[:alias]
|
87
79
|
|
88
80
|
@token = Sisimai::String.token(@addresser.address, @recipient.address, argvs['timestamp'])
|
89
81
|
@timestamp = Sisimai::Time.parse(::Time.at(argvs['timestamp']).to_s)
|
@@ -101,19 +93,10 @@ module Sisimai
|
|
101
93
|
@smtpcommand = argvs['smtpcommand'] || ''
|
102
94
|
@feedbacktype = argvs['feedbacktype'] || ''
|
103
95
|
@action = argvs['action'] || ''
|
104
|
-
@replycode =
|
96
|
+
@replycode = argvs['replycode'] || ''
|
97
|
+
@replycode = Sisimai::SMTP::Reply.find(argvs['diagnosticcode']) if @replycode.empty?
|
105
98
|
@softbounce = argvs['softbounce'] || ''
|
106
99
|
@softbounce = 1 if @replycode =~ /\A4/
|
107
|
-
|
108
|
-
if cv = @action.match(/\A(.+?) .+/)
|
109
|
-
@action = cv[1]
|
110
|
-
end
|
111
|
-
|
112
|
-
if @replycode.size > 0 && @deliverystatus.size > 0
|
113
|
-
# The first digits did not match: 5.1.1 250
|
114
|
-
@replycode = '' unless @replycode[0, 1] == @deliverystatus[0, 1]
|
115
|
-
end
|
116
|
-
|
117
100
|
end
|
118
101
|
|
119
102
|
# Another constructor of Sisimai::Data
|
@@ -127,11 +110,12 @@ module Sisimai
|
|
127
110
|
return nil unless data.is_a? Sisimai::Message
|
128
111
|
|
129
112
|
messageobj = data
|
113
|
+
mailheader = data.header
|
130
114
|
rfc822data = messageobj.rfc822
|
131
|
-
fieldorder = {
|
115
|
+
fieldorder = { :recipient => [], :addresser => [] }
|
132
116
|
objectlist = []
|
133
117
|
rxcommands = %r/\A(?:EHLO|HELO|MAIL|RCPT|DATA|QUIT)\z/
|
134
|
-
givenorder = argvs[
|
118
|
+
givenorder = argvs[:order] || {}
|
135
119
|
delivered1 = argvs[:delivered] || false
|
136
120
|
|
137
121
|
return nil unless messageobj.ds
|
@@ -169,6 +153,7 @@ module Sisimai
|
|
169
153
|
'alias' => e['alias'] || '',
|
170
154
|
'action' => e['action'] || '',
|
171
155
|
'reason' => e['reason'] || '',
|
156
|
+
'replycode' => e['replycode'] || '',
|
172
157
|
'smtpagent' => e['agent'] || '',
|
173
158
|
'recipient' => e['recipient'] || '',
|
174
159
|
'softbounce' => e['softbounce'] || '',
|
@@ -185,7 +170,7 @@ module Sisimai
|
|
185
170
|
|
186
171
|
# EMAIL_ADDRESS:
|
187
172
|
# Detect email address from message/rfc822 part
|
188
|
-
fieldorder[
|
173
|
+
fieldorder[:addresser].each do |f|
|
189
174
|
# Check each header in message/rfc822 part
|
190
175
|
h = f.downcase
|
191
176
|
next unless rfc822data.key?(h)
|
@@ -213,7 +198,7 @@ module Sisimai
|
|
213
198
|
end
|
214
199
|
|
215
200
|
# Date information did not exist in message/delivery-status part,...
|
216
|
-
RFC822Head[
|
201
|
+
RFC822Head[:date].each do |f|
|
217
202
|
# Get the value of Date header or other date related header.
|
218
203
|
next unless rfc822data[f.downcase]
|
219
204
|
datevalues << rfc822data[f.downcase]
|
@@ -251,6 +236,14 @@ module Sisimai
|
|
251
236
|
next unless p['timestamp']
|
252
237
|
|
253
238
|
# OTHER_TEXT_HEADERS:
|
239
|
+
if mailheader['received'].size > 0
|
240
|
+
# Get localhost and remote host name from Received header.
|
241
|
+
r0 = mailheader['received']
|
242
|
+
%w|lhost rhost|.each { |a| e[a] ||= '' }
|
243
|
+
e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
|
244
|
+
e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
|
245
|
+
end
|
246
|
+
|
254
247
|
# Remove square brackets and curly brackets from the host variable
|
255
248
|
%w|rhost lhost|.each do |v|
|
256
249
|
p[v] = p[v].delete('[]()') # Remove square brackets and curly brackets from the host variable
|
@@ -301,9 +294,33 @@ module Sisimai
|
|
301
294
|
p['deliverystatus'] = d
|
302
295
|
end
|
303
296
|
|
297
|
+
if p['reason'] == 'mailererror'
|
298
|
+
p['diagnostictype'] ||= 'X-UNIX'
|
299
|
+
else
|
300
|
+
unless p['reason'] =~ /\A(?:feedback|vacation)\z/
|
301
|
+
p['diagnostictype'] ||= 'SMTP'
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
304
305
|
# Check the value of SMTP command
|
305
306
|
p['smtpcommand'] = '' unless p['smtpcommand'] =~ rxcommands
|
306
307
|
|
308
|
+
# Check the value of "action"
|
309
|
+
if p['action'].size > 0
|
310
|
+
if cv = p['action'].match(/\A(.+?) .+/)
|
311
|
+
# Action: expanded (to multi-recipient alias)
|
312
|
+
p['action'] = cv[1]
|
313
|
+
end
|
314
|
+
else
|
315
|
+
if p['reason'] == 'expired'
|
316
|
+
# Action: delayed
|
317
|
+
p['action'] = 'delayed'
|
318
|
+
elsif p['deliverystatus'] =~ /\A[45]/
|
319
|
+
# Action: failed
|
320
|
+
p['action'] = 'failed'
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
307
324
|
o = Sisimai::Data.new(p)
|
308
325
|
next unless o.recipient
|
309
326
|
|
@@ -357,9 +374,16 @@ module Sisimai
|
|
357
374
|
end
|
358
375
|
end
|
359
376
|
end
|
377
|
+
|
378
|
+
if o.replycode.size > 0
|
379
|
+
# Check both of the first digit of "deliverystatus" and "replycode"
|
380
|
+
o.replycode = '' unless o.replycode[0, 1] == o.deliverystatus[0, 1]
|
381
|
+
end
|
382
|
+
|
360
383
|
else
|
361
384
|
# The value of reason is "vacation" or "feedback"
|
362
385
|
o.softbounce = -1
|
386
|
+
o.replycode = ''
|
363
387
|
end
|
364
388
|
objectlist << o
|
365
389
|
end
|
data/lib/sisimai/datetime.rb
CHANGED
@@ -14,170 +14,170 @@ module Sisimai
|
|
14
14
|
TZ_OFFSET = 54000 # Max time zone offset, 54000 seconds
|
15
15
|
|
16
16
|
TimeUnit = {
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
17
|
+
o: (BASE_D * BASE_Y * 4), # Olympiad, 4 years
|
18
|
+
y: (BASE_D * BASE_Y), # Year, Gregorian Calendar
|
19
|
+
q: (BASE_D * BASE_Y / 4), # Quarter, year/4
|
20
|
+
l: (BASE_D * BASE_L), # Lunar month
|
21
|
+
f: (BASE_D * 14), # Fortnight, 2 weeks
|
22
|
+
w: (BASE_D * 7), # Week, 604800 seconds
|
23
|
+
d: BASE_D, # Day
|
24
|
+
h: 3600, # Hour
|
25
|
+
b: 86.4, # Beat, Swatch internet time: 1000b = 1d
|
26
|
+
m: 60, # Minute,
|
27
|
+
s: 1, # Second
|
28
28
|
}
|
29
29
|
|
30
30
|
MathematicalConstant = {
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
e: CONST_E,
|
32
|
+
p: CONST_P,
|
33
|
+
g: CONST_E**CONST_P,
|
34
34
|
}
|
35
35
|
|
36
36
|
MonthName = {
|
37
|
-
|
38
|
-
|
37
|
+
full: %w|January February March April May June July August September October November December|,
|
38
|
+
abbr: %w|Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec|,
|
39
39
|
}
|
40
40
|
|
41
41
|
DayOfWeek = {
|
42
|
-
|
43
|
-
|
42
|
+
full: %w|Sunday Monday Tuesday Wednesday Thursday Friday Saturday|,
|
43
|
+
abbr: %w|Sun Mon Tue Wed Thu Fri Sat |,
|
44
44
|
}
|
45
45
|
|
46
46
|
HourName = {
|
47
|
-
|
47
|
+
full: [
|
48
48
|
'Midnight', 1, 2, 3, 4, 5, 'Morning', 7, 8, 9, 10, 11,
|
49
49
|
'Noon', 13, 14, 15, 16, 17, 'Evening', 19, 20, 21, 22, 23,
|
50
50
|
],
|
51
|
-
|
51
|
+
abbr: [0..23],
|
52
52
|
}
|
53
53
|
|
54
54
|
TimeZoneAbbr = {
|
55
55
|
# http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
|
64
|
-
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
|
121
|
-
#
|
122
|
-
#
|
123
|
-
|
124
|
-
|
125
|
-
#
|
126
|
-
#
|
127
|
-
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
144
|
-
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
|
154
|
-
#
|
155
|
-
#
|
156
|
-
#
|
157
|
-
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
|
170
|
-
|
171
|
-
#
|
172
|
-
#
|
173
|
-
#
|
174
|
-
#
|
175
|
-
#
|
176
|
-
#
|
177
|
-
#
|
178
|
-
#
|
179
|
-
#
|
180
|
-
#
|
56
|
+
# ACDT: '+1030', # Australian Central Daylight Time UTC+10:30
|
57
|
+
# ACST: '+0930', # Australian Central Standard Time UTC+09:30
|
58
|
+
# ACT: '+0800', # ASEAN Common Time UTC+08:00
|
59
|
+
ADT: '-0300', # Atlantic Daylight Time UTC-03:00
|
60
|
+
# AEDT: '+1100', # Australian Eastern Daylight Time UTC+11:00
|
61
|
+
# AEST: '+1000', # Australian Eastern Standard Time UTC+10:00
|
62
|
+
# AFT: '+0430', # Afghanistan Time UTC+04:30
|
63
|
+
AKDT: '-0800', # Alaska Daylight Time UTC-08:00
|
64
|
+
AKST: '-0900', # Alaska Standard Time UTC-09:00
|
65
|
+
# AMST '+0500', # Armenia Summer Time UTC+05:00
|
66
|
+
# AMT '+0400', # Armenia Time UTC+04:00
|
67
|
+
# ART '-0300', # Argentina Time UTC+03:00
|
68
|
+
# AST '+0300', # Arab Standard Time (Kuwait, Riyadh) UTC+03:00
|
69
|
+
# AST '+0400', # Arabian Standard Time (Abu Dhabi, Muscat) UTC+04:00
|
70
|
+
# AST '+0300', # Arabic Standard Time (Baghdad) UTC+03:00
|
71
|
+
AST: '-0400', # Atlantic Standard Time UTC-04:00
|
72
|
+
# AWDT: '+0900', # Australian Western Daylight Time UTC+09:00
|
73
|
+
# AWST: '+0800', # Australian Western Standard Time UTC+08:00
|
74
|
+
# AZOST: '-0100', # Azores Standard Time UTC-01:00
|
75
|
+
# AZT: '+0400', # Azerbaijan Time UTC+04:00
|
76
|
+
# BDT: '+0800', # Brunei Time UTC+08:00
|
77
|
+
# BIOT: '+0600', # British Indian Ocean Time UTC+06:00
|
78
|
+
# BIT: '-1200', # Baker Island Time UTC-12:00
|
79
|
+
# BOT: '-0400', # Bolivia Time UTC-04:00
|
80
|
+
# BRT: '-0300', # Brasilia Time UTC-03:00
|
81
|
+
# BST: '+0600', # Bangladesh Standard Time UTC+06:00
|
82
|
+
# BST: '+0100', # British Summer Time (British Standard Time from Feb 1968 to Oct 1971) UTC+01:00
|
83
|
+
# BTT: '+0600', # Bhutan Time UTC+06:00
|
84
|
+
# CAT: '+0200', # Central Africa Time UTC+02:00
|
85
|
+
# CCT: '+0630', # Cocos Islands Time UTC+06:30
|
86
|
+
CDT: '-0500', # Central Daylight Time (North America) UTC-05:00
|
87
|
+
# CEDT: '+0200', # Central European Daylight Time UTC+02:00
|
88
|
+
# CEST: '+0200', # Central European Summer Time UTC+02:00
|
89
|
+
# CET: '+0100', # Central European Time UTC+01:00
|
90
|
+
# CHAST: '+1245', # Chatham Standard Time UTC+12:45
|
91
|
+
# CIST: '-0800', # Clipperton Island Standard Time UTC-08:00
|
92
|
+
# CKT: '-1000', # Cook Island Time UTC-10:00
|
93
|
+
# CLST '-0300', # Chile Summer Time UTC-03:00
|
94
|
+
# CLT '-0400', # Chile Standard Time UTC-04:00
|
95
|
+
# COST '-0400', # Colombia Summer Time UTC-04:00
|
96
|
+
# COT '-0500', # Colombia Time UTC-05:00
|
97
|
+
CST: '-0600', # Central Standard Time (North America) UTC-06:00
|
98
|
+
# CST: '+0800', # China Standard Time UTC+08:00
|
99
|
+
# CVT: '-0100', # Cape Verde Time UTC-01:00
|
100
|
+
# CXT: '+0700', # Christmas Island Time UTC+07:00
|
101
|
+
# ChST: '+1000', # Chamorro Standard Time UTC+10:00
|
102
|
+
# DST: '' # Daylight saving time Depending
|
103
|
+
# DFT: '+0100', # AIX specific equivalent of Central European Time UTC+01:00
|
104
|
+
# EAST: '-0600', # Easter Island Standard Time UTC-06:00
|
105
|
+
# EAT: '+0300', # East Africa Time UTC+03:00
|
106
|
+
# ECT: '-0400', # Eastern Caribbean Time (does not recognise DST) UTC-04:00
|
107
|
+
# ECT: '-0500', # Ecuador Time UTC-05:00
|
108
|
+
EDT: '-0400', # Eastern Daylight Time (North America) UTC-04:00
|
109
|
+
# EEDT: '+0300', # Eastern European Daylight Time UTC+03:00
|
110
|
+
# EEST: '+0300', # Eastern European Summer Time UTC+03:00
|
111
|
+
# EET: '+0200', # Eastern European Time UTC+02:00
|
112
|
+
EST: '+0500', # Eastern Standard Time (North America) UTC-05:00
|
113
|
+
# FJT: '+1200', # Fiji Time UTC+12:00
|
114
|
+
# FKST: '-0400', # Falkland Islands Standard Time UTC-04:00
|
115
|
+
# GALT: '-0600', # Galapagos Time UTC-06:00
|
116
|
+
# GET: '+0400', # Georgia Standard Time UTC+04:00
|
117
|
+
# GFT: '-0300', # French Guiana Time UTC-03:00
|
118
|
+
# GILT: '+1200', # Gilbert Island Time UTC+12:00
|
119
|
+
# GIT: '-0900', # Gambier Island Time UTC-09:00
|
120
|
+
GMT: '+0000', # Greenwich Mean Time UTC
|
121
|
+
# :GST '-0200', # South Georgia and the South Sandwich Islands UTC-02:00
|
122
|
+
# :GYT '-0400', # Guyana Time UTC-04:00
|
123
|
+
HADT: '-0900', # Hawaii-Aleutian Daylight Time UTC-09:00
|
124
|
+
HAST: '-1000', # Hawaii-Aleutian Standard Time UTC-10:00
|
125
|
+
# HKT: '+0800', # Hong Kong Time UTC+08:00
|
126
|
+
# HMT: '+0500', # Heard and McDonald Islands Time UTC+05:00
|
127
|
+
HST: '-1000', # Hawaii Standard Time UTC-10:00
|
128
|
+
# IRKT: '+0800', # Irkutsk Time UTC+08:00
|
129
|
+
# IRST: '+0330', # Iran Standard Time UTC+03:30
|
130
|
+
# IST: '+0530', # Indian Standard Time UTC+05:30
|
131
|
+
# IST: '+0100', # Irish Summer Time UTC+01:00
|
132
|
+
# IST: '+0200', # Israel Standard Time UTC+02:00
|
133
|
+
JST: '+0900', # Japan Standard Time UTC+09:00
|
134
|
+
# KRAT: '+0700', # Krasnoyarsk Time UTC+07:00
|
135
|
+
# KST: '+0900', # Korea Standard Time UTC+09:00
|
136
|
+
# LHST: '+1030', # Lord Howe Standard Time UTC+10:30
|
137
|
+
# LINT: '+1400', # Line Islands Time UTC+14:00
|
138
|
+
# MAGT: '+1100', # Magadan Time UTC+11:00
|
139
|
+
MDT: '-0600', # Mountain Daylight Time(North America) UTC-06:00
|
140
|
+
# MIT: '-0930', # Marquesas Islands Time UTC-09:30
|
141
|
+
# MSD: '+0400', # Moscow Summer Time UTC+04:00
|
142
|
+
# MSK: '+0300', # Moscow Standard Time UTC+03:00
|
143
|
+
# MST: '+0800', # Malaysian Standard Time UTC+08:00
|
144
|
+
MST: '-0700', # Mountain Standard Time(North America) UTC-07:00
|
145
|
+
# MST: '+0630', # Myanmar Standard Time UTC+06:30
|
146
|
+
# MUT: '+0400', # Mauritius Time UTC+04:00
|
147
|
+
# NDT: '-0230', # Newfoundland Daylight Time UTC-02:30
|
148
|
+
# NFT: '+1130', # Norfolk Time[1] UTC+11:30
|
149
|
+
# NPT: '+0545', # Nepal Time UTC+05:45
|
150
|
+
# NST: '-0330', # Newfoundland Standard Time UTC-03:30
|
151
|
+
# NT: '-0330', # Newfoundland Time UTC-03:30
|
152
|
+
# OMST: '+0600', # Omsk Time UTC+06:00
|
153
|
+
PDT: '-0700', # Pacific Daylight Time(North America) UTC-07:00
|
154
|
+
# PETT: '+1200', # Kamchatka Time UTC+12:00
|
155
|
+
# PHOT: '+1300', # Phoenix Island Time UTC+13:00
|
156
|
+
# PKT: '+0500', # Pakistan Standard Time UTC+05:00
|
157
|
+
PST: '-0800', # Pacific Standard Time (North America) UTC-08:00
|
158
|
+
# PST: '+0800', # Philippine Standard Time UTC+08:00
|
159
|
+
# RET: '+0400', # Reunion Time UTC+04:00
|
160
|
+
# SAMT: '+0400', # Samara Time UTC+04:00
|
161
|
+
# SAST: '+0200', # South African Standard Time UTC+02:00
|
162
|
+
# SBT: '+1100', # Solomon Islands Time UTC+11:00
|
163
|
+
# SCT: '+0400', # Seychelles Time UTC+04:00
|
164
|
+
# SLT: '+0530', # Sri Lanka Time UTC+05:30
|
165
|
+
# SST: '-1100', # Samoa Standard Time UTC-11:00
|
166
|
+
# SST: '+0800', # Singapore Standard Time UTC+08:00
|
167
|
+
# TAHT: '-1000', # Tahiti Time UTC-10:00
|
168
|
+
# THA: '+0700', # Thailand Standard Time UTC+07:00
|
169
|
+
UT: '-0000', # Coordinated Universal Time UTC
|
170
|
+
UTC: '-0000', # Coordinated Universal Time UTC
|
171
|
+
# UYST: '-0200', # Uruguay Summer Time UTC-02:00
|
172
|
+
# UYT: '-0300', # Uruguay Standard Time UTC-03:00
|
173
|
+
# VET: '-0430', # Venezuelan Standard Time UTC-04:30
|
174
|
+
# VLAT: '+1000', # Vladivostok Time UTC+10:00
|
175
|
+
# WAT: '+0100', # West Africa Time UTC+01:00
|
176
|
+
# WEDT: '+0100', # Western European Daylight Time UTC+01:00
|
177
|
+
# WEST: '+0100', # Western European Summer Time UTC+01:00
|
178
|
+
# WET: '-0000', # Western European Time UTC
|
179
|
+
# YAKT: '+0900', # Yakutsk Time UTC+09:00
|
180
|
+
# YEKT: '+0500', # Yekaterinburg Time UTC+05:00
|
181
181
|
}
|
182
182
|
|
183
183
|
# Convert to second
|
@@ -198,15 +198,15 @@ module Sisimai
|
|
198
198
|
# 1d, 1.5w
|
199
199
|
n = cr[1].to_f
|
200
200
|
u = cr[2] || 'd'
|
201
|
-
getseconds = n * TimeUnit[u].to_f
|
201
|
+
getseconds = n * TimeUnit[u.to_sym].to_f
|
202
202
|
|
203
203
|
elsif cr = argv1.match(/\A(\d+|\d+[.]\d+)?([#{mathconsts}])([#{unitoftime}])?\z/)
|
204
204
|
# 1pd, 1.5pw
|
205
205
|
n = cr[1].to_f || 1
|
206
206
|
n = 1 if n.to_i == 0
|
207
|
-
m = MathematicalConstant[cr[2]].to_f
|
207
|
+
m = MathematicalConstant[cr[2].to_sym].to_f
|
208
208
|
u = cr[3] || 'd'
|
209
|
-
getseconds = n * m * TimeUnit[u].to_f
|
209
|
+
getseconds = n * m * TimeUnit[u.to_sym].to_f
|
210
210
|
|
211
211
|
else
|
212
212
|
getseconds = 0
|
@@ -223,7 +223,7 @@ module Sisimai
|
|
223
223
|
# monthname() #=> [ 'Jan', 'Feb', ... ]
|
224
224
|
# monthname(1) #=> [ 'January', 'February', 'March', ... ]
|
225
225
|
def monthname(argv1 = 0)
|
226
|
-
value = argv1 > 0 ?
|
226
|
+
value = argv1 > 0 ? :full : :abbr
|
227
227
|
return MonthName[value]
|
228
228
|
end
|
229
229
|
|
@@ -234,7 +234,7 @@ module Sisimai
|
|
234
234
|
# dayofweek() #=> [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]
|
235
235
|
# dayofweek(1) #=> [ 'Sunday', 'Monday', 'Tuesday', ... ]
|
236
236
|
def dayofweek(argv1 = 0)
|
237
|
-
value = argv1 > 0 ?
|
237
|
+
value = argv1 > 0 ? :full : :abbr
|
238
238
|
return DayOfWeek[value]
|
239
239
|
end
|
240
240
|
|
@@ -245,7 +245,7 @@ module Sisimai
|
|
245
245
|
# hourname() #=> [ 0, 1, 2, ... 23 ]
|
246
246
|
# hourname(1) #=> [ 'Midnight', 1, 2, ... 'Morning', 7, ... 'Noon', ... 23 ]
|
247
247
|
def hourname(argv1 = 1)
|
248
|
-
value = argv1 > 0 ?
|
248
|
+
value = argv1 > 0 ? :full : :abbr
|
249
249
|
return HourName[value]
|
250
250
|
end
|
251
251
|
|
@@ -292,12 +292,12 @@ module Sisimai
|
|
292
292
|
afternoon1 = 0 # (Integer) After noon flag
|
293
293
|
altervalue = {} # (Hash) To store alternative values
|
294
294
|
v = {
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
295
|
+
Y: nil, # (Integer) Year
|
296
|
+
M: nil, # (String) Month Abbr.
|
297
|
+
d: nil, # (Integer) Day
|
298
|
+
a: nil, # (String) Day of week, Abbr.
|
299
|
+
T: nil, # (String) Time
|
300
|
+
z: nil, # (Integer) Timezone offset
|
301
301
|
}
|
302
302
|
|
303
303
|
while p = timetokens.shift do
|
@@ -306,13 +306,13 @@ module Sisimai
|
|
306
306
|
# Day of week or Day of week; Thu, Apr, ...
|
307
307
|
p.chop if p.length == 4 # Thu, -> Thu
|
308
308
|
|
309
|
-
if DayOfWeek[
|
309
|
+
if DayOfWeek[:abbr].include?(p)
|
310
310
|
# Day of week; Mon, Thu, Sun,...
|
311
|
-
v[
|
311
|
+
v[:a] = p
|
312
312
|
|
313
|
-
elsif MonthName[
|
313
|
+
elsif MonthName[:abbr].include?(p)
|
314
314
|
# Month name abbr.; Apr, May, ...
|
315
|
-
v[
|
315
|
+
v[:M] = p
|
316
316
|
|
317
317
|
end
|
318
318
|
|
@@ -320,16 +320,16 @@ module Sisimai
|
|
320
320
|
# Year or Day; 2005, 31, 04, 1, ...
|
321
321
|
if p.to_i > 31
|
322
322
|
# The piece is the value of an year
|
323
|
-
v[
|
323
|
+
v[:Y] = p
|
324
324
|
|
325
325
|
else
|
326
326
|
# The piece is the value of a day
|
327
|
-
if v[
|
327
|
+
if v[:d]
|
328
328
|
# 2-digit year?
|
329
|
-
altervalue[
|
329
|
+
altervalue[:Y] = p unless v[:Y]
|
330
330
|
else
|
331
331
|
# The value is "day"
|
332
|
-
v[
|
332
|
+
v[:d] = p
|
333
333
|
end
|
334
334
|
end
|
335
335
|
|
@@ -340,18 +340,18 @@ module Sisimai
|
|
340
340
|
|
341
341
|
if cr[1].to_i < 24 && cr[2].to_i < 60 && cr[3].to_i < 60
|
342
342
|
# Valid time format, maybe...
|
343
|
-
v[
|
343
|
+
v[:T] = sprintf('%02d:%02d:%02d', cr[1].to_i, cr[2].to_i, cr[3].to_i)
|
344
344
|
end
|
345
345
|
|
346
346
|
elsif cr = p.match(/\A([0-2]\d):([0-5]\d)\z/)
|
347
347
|
# Time; 12:34 => 12:34:00
|
348
348
|
if cr[1].to_i < 24 && cr[2].to_i < 60
|
349
|
-
v[
|
349
|
+
v[:T] = sprintf('%02d:%02d:00', cr[1], cr[2])
|
350
350
|
end
|
351
351
|
|
352
352
|
elsif cr = p.match(/\A(\d\d?):(\d\d?)\z/)
|
353
353
|
# Time: 1:4 => 01:04:00
|
354
|
-
v[
|
354
|
+
v[:T] = sprintf('%02d:%02d:00', cr[1], cr[2])
|
355
355
|
|
356
356
|
elsif p =~ /\A[APap][Mm]\z/
|
357
357
|
# AM or PM
|
@@ -361,68 +361,68 @@ module Sisimai
|
|
361
361
|
# Timezone offset and others
|
362
362
|
if p =~ /\A[-+][01]\d{3}\z/
|
363
363
|
# Timezone offset; +0000, +0900, -1000, ...
|
364
|
-
v[
|
364
|
+
v[:z] ||= p
|
365
365
|
|
366
366
|
elsif p =~ /\A[(]?[A-Z]{2,5}[)]?\z/
|
367
367
|
# Timezone abbreviation; JST, GMT, UTC, ...
|
368
|
-
v[
|
368
|
+
v[:z] ||= abbr2tz(p) || '+0000'
|
369
369
|
|
370
370
|
else
|
371
371
|
# Other date format
|
372
372
|
if cr = p.match(%r|\A(\d{4})[-/](\d{1,2})[-/](\d{1,2})\z|)
|
373
373
|
# Mail.app(MacOS X)'s faked Bounce, Arrival-Date: 2010-06-18 17:17:52 +0900
|
374
|
-
v[
|
375
|
-
v[
|
376
|
-
v[
|
374
|
+
v[:Y] = cr[1].to_i
|
375
|
+
v[:M] = MonthName[:abbr][cr[2].to_i - 1]
|
376
|
+
v[:d] = cr[3].to_i
|
377
377
|
|
378
378
|
elsif cr = p.match(%r|\A(\d{4})[-/](\d{1,2})[-/](\d{1,2})T([0-2]\d):([0-5]\d):([0-5]\d)\z|)
|
379
379
|
# ISO 8601; 2000-04-29T01:23:45
|
380
|
-
v[
|
381
|
-
v[
|
380
|
+
v[:Y] = cr[1].to_i
|
381
|
+
v[:M] = MonthName[:abbr][cr[2].to_i - 1]
|
382
382
|
|
383
383
|
if cr[3].to_i < 32
|
384
|
-
v[
|
384
|
+
v[:d] = cr[3].to_i
|
385
385
|
end
|
386
386
|
|
387
387
|
if cr[4].to_i < 24 && cr[5].to_i < 60 && cr[6].to_i < 60
|
388
|
-
v[
|
388
|
+
v[:T] = sprintf('%02d:%02d:%02d', cr[4], cr[5], cr[6])
|
389
389
|
end
|
390
390
|
|
391
391
|
elsif cr = p.match(%r|\A(\d{1,2})/(\d{1,2})/(\d{1,2})\z|)
|
392
392
|
# 4/29/01 11:34:45 PM
|
393
|
-
v[
|
394
|
-
v[
|
395
|
-
v[
|
396
|
-
v[
|
393
|
+
v[:M] = MonthName[:abbr][cr[1].to_i - 1]
|
394
|
+
v[:d] = cr[2].to_i
|
395
|
+
v[:Y] = cr[3].to_i + 2000
|
396
|
+
v[:Y] -= 100 if v[:Y].to_i > ::DateTime.now.year + 1
|
397
397
|
end
|
398
398
|
end
|
399
399
|
end
|
400
400
|
end # End of while()
|
401
401
|
|
402
|
-
if v[
|
402
|
+
if v[:T] && afternoon1 > 0
|
403
403
|
# +12
|
404
|
-
t0 = v[
|
405
|
-
t1 = v[
|
406
|
-
v[
|
407
|
-
v[
|
404
|
+
t0 = v[:T]
|
405
|
+
t1 = v[:T].split(':')
|
406
|
+
v[:T] = sprintf('%02d:%02d:%02d', t1[0].to_i + 12, t1[1], t1[2])
|
407
|
+
v[:T] = t0 if t1[0].to_i > 12
|
408
408
|
end
|
409
|
-
v[
|
409
|
+
v[:a] ||= 'Thu' # There is no day of week
|
410
410
|
|
411
|
-
if !v[
|
411
|
+
if !v[:Y].nil? && v[:Y].to_i < 200
|
412
412
|
# 99 -> 1999, 102 -> 2002
|
413
|
-
v[
|
413
|
+
v[:Y] = v[:Y].to_i + 1900
|
414
414
|
end
|
415
|
-
v[
|
415
|
+
v[:z] ||= ::DateTime.now.zone.delete(':')
|
416
416
|
|
417
417
|
# Adjust 2-digit Year
|
418
|
-
if altervalue[
|
418
|
+
if altervalue[:Y] && !v[:Y]
|
419
419
|
# Check alternative value(Year)
|
420
|
-
if altervalue[
|
420
|
+
if altervalue[:Y].to_i >= 82
|
421
421
|
# SMTP was born in 1982
|
422
|
-
v[
|
422
|
+
v[:Y] ||= 1900 + altervalue[:Y].to_i
|
423
423
|
else
|
424
424
|
# 20XX
|
425
|
-
v[
|
425
|
+
v[:Y] ||= 2000 + altervalue[:Y].to_i
|
426
426
|
end
|
427
427
|
end
|
428
428
|
|
@@ -433,14 +433,14 @@ module Sisimai
|
|
433
433
|
return nil
|
434
434
|
end
|
435
435
|
|
436
|
-
if v[
|
436
|
+
if v[:Y].to_i < 1902 || v[:Y].to_i > 2037
|
437
437
|
# -(2^31) ~ (2^31)
|
438
438
|
return nil
|
439
439
|
end
|
440
440
|
|
441
441
|
# Build date string
|
442
442
|
# Thu, 29 Apr 2004 10:01:11 +0900
|
443
|
-
return sprintf('%s, %s %s %s %s %s', v[
|
443
|
+
return sprintf('%s, %s %s %s %s %s', v[:a], v[:d], v[:M], v[:Y], v[:T], v[:z])
|
444
444
|
end
|
445
445
|
|
446
446
|
# Abbreviation -> Tiemzone
|
@@ -451,7 +451,7 @@ module Sisimai
|
|
451
451
|
# abbr2tz('JST') #=> '+0900'
|
452
452
|
def abbr2tz(argv1)
|
453
453
|
return nil unless argv1.is_a?(::String)
|
454
|
-
return TimeZoneAbbr[argv1]
|
454
|
+
return TimeZoneAbbr[argv1.to_sym]
|
455
455
|
end
|
456
456
|
|
457
457
|
# Convert to second
|
@@ -467,20 +467,20 @@ module Sisimai
|
|
467
467
|
|
468
468
|
if cr = argv1.match(/\A([-+])(\d)(\d)(\d{2})\z/)
|
469
469
|
digit = {
|
470
|
-
'operator' => cr[1],
|
471
|
-
'hour-10' => cr[2].to_i,
|
472
|
-
'hour-01' => cr[3].to_i,
|
473
|
-
'minutes' => cr[4].to_i,
|
470
|
+
:'operator' => cr[1],
|
471
|
+
:'hour-10' => cr[2].to_i,
|
472
|
+
:'hour-01' => cr[3].to_i,
|
473
|
+
:'minutes' => cr[4].to_i,
|
474
474
|
}
|
475
|
-
ztime += (digit['hour-10'] * 10 + digit['hour-01']) * 3600
|
476
|
-
ztime += (digit['minutes'] * 60)
|
477
|
-
ztime *= -1 if digit['operator'] == '-'
|
475
|
+
ztime += (digit[:'hour-10'] * 10 + digit[:'hour-01']) * 3600
|
476
|
+
ztime += (digit[:'minutes'] * 60)
|
477
|
+
ztime *= -1 if digit[:'operator'] == '-'
|
478
478
|
|
479
479
|
return nil if ztime.abs > TZ_OFFSET
|
480
480
|
return ztime
|
481
481
|
|
482
482
|
elsif argv1 =~ /\A[A-Za-z]+\z/
|
483
|
-
return tz2second(TimeZoneAbbr[argv1])
|
483
|
+
return tz2second(TimeZoneAbbr[argv1.to_sym])
|
484
484
|
|
485
485
|
else
|
486
486
|
return nil
|
@@ -495,14 +495,14 @@ module Sisimai
|
|
495
495
|
# second2tz(12345) #=> '+0325'
|
496
496
|
def second2tz(argv1)
|
497
497
|
return '+0000' unless argv1.is_a?(Number)
|
498
|
-
digit = {
|
498
|
+
digit = { :operator => '+' }
|
499
499
|
|
500
500
|
return '' if argv1.abs > TZ_OFFSET # UTC+14 + 1(DST?)
|
501
|
-
digit[
|
502
|
-
digit[
|
503
|
-
digit[
|
501
|
+
digit[:operator] = '-' if argv1 < 0
|
502
|
+
digit[:hours] = (argv1.abs / 3600).to_i
|
503
|
+
digit[:minutes] = ((argv1.abs % 3600) / 60).to_i
|
504
504
|
|
505
|
-
timez = sprintf('%s%02d%02d', digit[
|
505
|
+
timez = sprintf('%s%02d%02d', digit[:operator], digit[:hours], digit[:minutes])
|
506
506
|
return timez
|
507
507
|
end
|
508
508
|
end
|