embulk 0.8.36 → 0.8.37

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e53c57904a7874b17528ab6137cf1dbc74a807a5
4
- data.tar.gz: 371ca4d97fbaaf8870167962d0ca196c282598b9
3
+ metadata.gz: b48d88dbd34d7791315fabde49b264dab335024b
4
+ data.tar.gz: 08b8a533ac632ec41afc94dbe7106891a1ae854f
5
5
  SHA512:
6
- metadata.gz: b45b886e769a4b199cf5b67ec0be33e6bf087a94daecaba16367a94629a471d3fd299cf68e0016444a2362bee669841bd61c8a8dcf8a35a6d0ad25e07f2e2ced
7
- data.tar.gz: 2044b9df066673c2deaa4f687ac03bbd0cf03ce3d85ca24f10480537657f357862b4599f5852fa516be71ea5cbded64667e66ec1b32b196bf503c1990d3141bc
6
+ metadata.gz: 612667193d1ef43cfd11ae9c87faad0aeb1db3dc51d81834e97cafef48a8b4333dd57b28f982f3a0e91b8499c5fd454500b483a6fade6ce3ff18b2c276b5a55d
7
+ data.tar.gz: 84aa864147d51d67626a52917d63b99ab70e2a9c85b7e04ea735789073ad598681263544ac204893a026721011cbbe9f74b6c3a1b056a64d9e6b7c5cf79d6ee3
@@ -24,7 +24,7 @@ def release_projects = [project(":embulk-core"), project(":embulk-standards"), p
24
24
 
25
25
  allprojects {
26
26
  group = 'org.embulk'
27
- version = '0.8.36'
27
+ version = '0.8.37'
28
28
 
29
29
  ext {
30
30
  jrubyVersion = '9.1.13.0'
@@ -276,10 +276,14 @@ project(':embulk-cli') {
276
276
  }
277
277
  }
278
278
 
279
- task rubyTest(type: JRubyExec) {
280
- jrubyArgs '-Ilib', '-Itest', '-rtest/unit', '--debug', './test/run-test.rb'
279
+ task rubyTestVanilla(type: JRubyExec, dependsOn: "classpath") {
280
+ jrubyArgs '-Ilib', '-Itest', '-rtest/unit', '--debug', './test/vanilla/run-test.rb'
281
+ }
282
+ task rubyTestMonkeyStrptime(type: JRubyExec, dependsOn: "classpath") {
283
+ jrubyArgs '-Ilib', '-Itest', '-rtest/unit', '--debug', './test/monkey_strptime/run-test.rb'
284
+ }
285
+ task rubyTest(dependsOn: ["rubyTestVanilla", "rubyTestMonkeyStrptime"]) {
281
286
  }
282
- rubyTest.dependsOn('classpath')
283
287
 
284
288
  //
285
289
  // gem task
@@ -57,6 +57,12 @@ public class TimestampFormat
57
57
 
58
58
  public static DateTimeZone parseDateTimeZone(String s)
59
59
  {
60
+ final int rubyStyleTimeOffsetInSecond = TimeZoneConverter.dateZoneToDiff(s);
61
+
62
+ if (rubyStyleTimeOffsetInSecond != Integer.MIN_VALUE) {
63
+ return DateTimeZone.forOffsetMillis(rubyStyleTimeOffsetInSecond * 1000);
64
+ }
65
+
60
66
  if(s.startsWith("+") || s.startsWith("-")) {
61
67
  return DateTimeZone.forID(s);
62
68
 
@@ -187,7 +187,7 @@ public class TimestampParser
187
187
  // TODO cache parsed zone?
188
188
  timeZone = parseDateTimeZone(zone);
189
189
  if (timeZone == null) {
190
- throw new TimestampParseException("Invalid time zone name '" + text + "'");
190
+ throw new TimestampParseException("Invalid time zone name '" + zone + "' in '" + text + "'");
191
191
  }
192
192
  }
193
193
  else {
@@ -201,7 +201,24 @@ public class TimestampParser
201
201
  public LocalTime createLocalTimeFromFormatBag(FormatBag bag)
202
202
  {
203
203
  final long secFractionNsec;
204
- if (FormatBag.has(bag.getSecFraction())) {
204
+ if (FormatBag.has(bag.getSecondsSize())) { // %Q is specified.
205
+ // Fractions by %Q are prioritized over fractions by %N.
206
+ // irb(main):002:0> Time.strptime("123456789 12.345", "%Q %S.%N").nsec
207
+ // => 789000000
208
+ // irb(main):003:0> Time.strptime("12.345 123456789", "%S.%N %Q").nsec
209
+ // => 789000000
210
+ // irb(main):004:0> Time.strptime("12.345", "%S.%N").nsec
211
+ // => 345000000
212
+ if (bag.hasSeconds()) {
213
+ secFractionNsec = (bag.getSeconds() % (int)Math.pow(10, bag.getSecondsSize())) *
214
+ (int)Math.pow(10, 9 - bag.getSecondsSize());
215
+ }
216
+ else {
217
+ // It must not happen -- |seconds| is always set if |secondsSize| is set.
218
+ secFractionNsec = 0;
219
+ }
220
+ }
221
+ else if (FormatBag.has(bag.getSecFraction())) {
205
222
  secFractionNsec = bag.getSecFraction() * (int)Math.pow(10, 9 - bag.getSecFractionSize());
206
223
  }
207
224
  else {
@@ -228,11 +245,16 @@ public class TimestampParser
228
245
 
229
246
  // set up with min this and then add to allow rolling over
230
247
  DateTime dt = new DateTime(year, 1, 1, 0, 0, 0, 0, DateTimeZone.UTC);
231
- if (FormatBag.has(bag.getMon())) {
232
- dt = dt.plusMonths(bag.getMon() - 1);
248
+ if (FormatBag.has(bag.getYDay())) { // yday is more prioritized than mon/mday in Ruby's strptime.
249
+ dt = dt.plusDays(bag.getYDay() - 1);
233
250
  }
234
- if (FormatBag.has(bag.getMDay())) {
235
- dt = dt.plusDays(bag.getMDay() - 1);
251
+ else {
252
+ if (FormatBag.has(bag.getMon())) {
253
+ dt = dt.plusMonths(bag.getMon() - 1);
254
+ }
255
+ if (FormatBag.has(bag.getMDay())) {
256
+ dt = dt.plusDays(bag.getMDay() - 1);
257
+ }
236
258
  }
237
259
  if (FormatBag.has(bag.getHour())) {
238
260
  dt = dt.plusHours(bag.getHour());
@@ -241,7 +263,12 @@ public class TimestampParser
241
263
  dt = dt.plusMinutes(bag.getMin());
242
264
  }
243
265
  if (FormatBag.has(bag.getSec())) {
244
- dt = dt.plusSeconds(bag.getSec());
266
+ if (bag.getSec() == 60) { // Leap seconds are considered as 59 when Ruby converts them to epochs.
267
+ dt = dt.plusSeconds(59);
268
+ }
269
+ else {
270
+ dt = dt.plusSeconds(bag.getSec());
271
+ }
245
272
  }
246
273
  sec = dt.getMillis() / 1000;
247
274
  }
@@ -0,0 +1,232 @@
1
+ package org.embulk.spi.time;
2
+
3
+ import static org.junit.Assert.assertEquals;
4
+ import static org.junit.Assert.fail;
5
+
6
+ import org.joda.time.DateTimeZone;
7
+ import org.junit.Test;
8
+
9
+ /**
10
+ * TestTimestampParser tests org.embulk.spi.time.TimestampParser.
11
+ *
12
+ * Some test cases are imported from Ruby v2.3.1's test/date/test_date_strptime.rb. See its COPYING for license.
13
+ *
14
+ * @see <a href="https://svn.ruby-lang.org/cgi-bin/viewvc.cgi/tags/v2_3_1/test/date/test_date_strptime.rb?view=markup">test/date/test_date_strptime.rb</a>
15
+ * @see <a href="https://svn.ruby-lang.org/cgi-bin/viewvc.cgi/tags/v2_3_1/COPYING?view=markup">COPYING</a>
16
+ */
17
+ public class TestTimestampParser {
18
+ @Test // Imported from test__strptime__3 in Ruby v2.3.1's test/date/test_date_strptime.rb.
19
+ public void test__strptime__3_iso8601() {
20
+ testToParse("2001-02-03", "%Y-%m-%d", 981158400L);
21
+ testToParse("2001-02-03T23:59:60", "%Y-%m-%dT%H:%M:%S", 981244799L);
22
+ testToParse("2001-02-03T23:59:60+09:00", "%Y-%m-%dT%H:%M:%S%Z", 981212399L);
23
+ testToParse("-2001-02-03T23:59:60+09:00", "%Y-%m-%dT%H:%M:%S%Z", -125309754001L);
24
+ testToParse("+012345-02-03T23:59:60+09:00", "%Y-%m-%dT%H:%M:%S%Z", 327406287599L);
25
+ testToParse("-012345-02-03T23:59:60+09:00", "%Y-%m-%dT%H:%M:%S%Z", -451734829201L);
26
+ }
27
+
28
+ @Test // Imported from test__strptime__3 in Ruby v2.3.1's test/date/test_date_strptime.rb.
29
+ public void test__strptime__3_ctime3_asctime3() {
30
+ testToParse("Thu Jul 29 14:47:19 1999", "%c", 933259639L);
31
+ testToParse("Thu Jul 29 14:47:19 -1999", "%c", -125231389961L);
32
+ }
33
+
34
+ @Test // Imported from test__strptime__3 in Ruby v2.3.1's test/date/test_date_strptime.rb.
35
+ public void test__strptime__3_date1() {
36
+ testToParse("Thu Jul 29 16:39:41 EST 1999", "%a %b %d %H:%M:%S %Z %Y", 933284381L);
37
+ testToParse("Thu Jul 29 16:39:41 MET DST 1999", "%a %b %d %H:%M:%S %Z %Y", 933259181L);
38
+ // Their time zones are "AMT" actually in Ruby v2.3.1's tests, but "AST" is used here instead.
39
+ // "AMT" is not recognized even by Ruby v2.3.1's zonetab.
40
+ testToParse("Thu Jul 29 16:39:41 AST 1999", "%a %b %d %H:%M:%S %Z %Y", 933280781L);
41
+ testToParse("Thu Jul 29 16:39:41 AST -1999", "%a %b %d %H:%M:%S %Z %Y", -125231368819L);
42
+ testToParse("Thu Jul 29 16:39:41 GMT+09 1999", "%a %b %d %H:%M:%S %Z %Y", 933233981L);
43
+ testToParse("Thu Jul 29 16:39:41 GMT+0908 1999", "%a %b %d %H:%M:%S %Z %Y", 933233501L);
44
+ testToParse("Thu Jul 29 16:39:41 GMT+090807 1999", "%a %b %d %H:%M:%S %Z %Y", 933233494L);
45
+ testToParse("Thu Jul 29 16:39:41 GMT-09 1999", "%a %b %d %H:%M:%S %Z %Y", 933298781L);
46
+ testToParse("Thu Jul 29 16:39:41 GMT-09:08 1999", "%a %b %d %H:%M:%S %Z %Y", 933299261L);
47
+ testToParse("Thu Jul 29 16:39:41 GMT-09:08:07 1999", "%a %b %d %H:%M:%S %Z %Y", 933299268L);
48
+ testToParse("Thu Jul 29 16:39:41 GMT-3.5 1999", "%a %b %d %H:%M:%S %Z %Y", 933278981L);
49
+ testToParse("Thu Jul 29 16:39:41 GMT-3,5 1999", "%a %b %d %H:%M:%S %Z %Y", 933278981L);
50
+ testToParse("Thu Jul 29 16:39:41 Mountain Daylight Time 1999", "%a %b %d %H:%M:%S %Z %Y", 933287981L);
51
+ testToParse("Thu Jul 29 16:39:41 E. Australia Standard Time 1999", "%a %b %d %H:%M:%S %Z %Y", 933230381L);
52
+ }
53
+
54
+ @Test // Imported from test__strptime__3 in Ruby v2.3.1's test/date/test_date_strptime.rb.
55
+ public void test__strptime__3_rfc822() {
56
+ testToParse("Thu, 29 Jul 1999 09:54:21 UT", "%a, %d %b %Y %H:%M:%S %Z", 933242061L);
57
+ testToParse("Thu, 29 Jul 1999 09:54:21 GMT", "%a, %d %b %Y %H:%M:%S %Z", 933242061L);
58
+ testToParse("Thu, 29 Jul 1999 09:54:21 PDT", "%a, %d %b %Y %H:%M:%S %Z", 933267261L);
59
+ testToParse("Thu, 29 Jul 1999 09:54:21 z", "%a, %d %b %Y %H:%M:%S %Z", 933242061L);
60
+ testToParse("Thu, 29 Jul 1999 09:54:21 +0900", "%a, %d %b %Y %H:%M:%S %Z", 933209661L);
61
+ testToParse("Thu, 29 Jul 1999 09:54:21 +0430", "%a, %d %b %Y %H:%M:%S %Z", 933225861L);
62
+ testToParse("Thu, 29 Jul 1999 09:54:21 -0430", "%a, %d %b %Y %H:%M:%S %Z", 933258261L);
63
+ testToParse("Thu, 29 Jul -1999 09:54:21 -0430", "%a, %d %b %Y %H:%M:%S %Z", -125231391339L);
64
+ }
65
+
66
+ @Test // Imported from test__strptime__3 in Ruby v2.3.1's test/date/test_date_strptime.rb.
67
+ public void test__strptime__3_etc() {
68
+ testToParse("06-DEC-99", "%d-%b-%y", 944438400L);
69
+ testToParse("sUnDay oCtoBer 31 01", "%A %B %d %y", 1004486400L);
70
+ // Their "\u000b" are actually "\v" in Ruby v2.3.1's tests. "\v" is not recognized as a character in Java.
71
+ testToParse("October\t\n\u000b\f\r 15,\t\n\u000b\f\r99", "%B %d, %y", 939945600L);
72
+ testToParse("October\t\n\u000b\f\r 15,\t\n\u000b\f\r99", "%B%t%d,%n%y", 939945600L);
73
+
74
+ testToParse("09:02:11 AM", "%I:%M:%S %p", 81955357331L);
75
+ testToParse("09:02:11 A.M.", "%I:%M:%S %p", 81955357331L);
76
+ testToParse("09:02:11 PM", "%I:%M:%S %p", 81955400531L);
77
+ testToParse("09:02:11 P.M.", "%I:%M:%S %p", 81955400531L);
78
+
79
+ testToParse("12:33:44 AM", "%r", 81955326824L);
80
+ testToParse("01:33:44 AM", "%r", 81955330424L);
81
+ testToParse("11:33:44 AM", "%r", 81955366424L);
82
+ testToParse("12:33:44 PM", "%r", 81955370024L);
83
+ testToParse("01:33:44 PM", "%r", 81955373624L);
84
+ testToParse("11:33:44 PM", "%r", 81955409624L);
85
+
86
+ // Their time zones are "AMT" actually in Ruby v2.3.1's tests, but "AST" is used here instead.
87
+ // "AMT" is not recognized even by Ruby v2.3.1's zonetab.
88
+ testToParse("11:33:44 PM AST", "%I:%M:%S %p %Z", 81955424024L);
89
+ testToParse("11:33:44 P.M. AST", "%I:%M:%S %p %Z", 81955424024L);
90
+
91
+ testToParse("fri1feb034pm+5", "%a%d%b%y%H%p%Z", 1044097200L);
92
+ }
93
+
94
+ @Test // Imported from test__strptime__width in Ruby v2.3.1's test/date/test_date_strptime.rb.
95
+ public void test__strptime__width() {
96
+ testToParse("99", "%y", 917049600L);
97
+ testToParse("01", "%y", 980208000L);
98
+ testToParse("19 99", "%C %y", 917049600L);
99
+ testToParse("20 01", "%C %y", 980208000L);
100
+ testToParse("30 99", "%C %y", 35629718400L);
101
+ testToParse("30 01", "%C %y", 32537116800L);
102
+ testToParse("1999", "%C%y", 917049600L);
103
+ testToParse("2001", "%C%y", 980208000L);
104
+ testToParse("3099", "%C%y", 35629718400L);
105
+ testToParse("3001", "%C%y", 32537116800L);
106
+
107
+ testToParse("20060806", "%Y", 632995726752000L);
108
+ // Its " " is actually "\s" in Ruby v2.3.1's tests. "\s" is not recognized as a character in Java.
109
+ testToParse("20060806", "%Y ", 632995726752000L);
110
+ testToParse("20060806", "%Y%m%d", 1154822400L);
111
+ testToParse("2006908906", "%Y9%m9%d", 1154822400L);
112
+ testToParse("12006 08 06", "%Y %m %d", 316724342400L);
113
+ testToParse("12006-08-06", "%Y-%m-%d", 316724342400L);
114
+ testToParse("200608 6", "%Y%m%e", 1154822400L);
115
+
116
+ testToParse("2006333", "%Y%j", 1164758400L);
117
+ testToParse("20069333", "%Y9%j", 1164758400L);
118
+ testToParse("12006 333", "%Y %j", 316734278400L);
119
+ testToParse("12006-333", "%Y-%j", 316734278400L);
120
+
121
+ testToParse("232425", "%H%M%S", 81955409065L);
122
+ testToParse("23924925", "%H9%M9%S", 81955409065L);
123
+ testToParse("23 24 25", "%H %M %S", 81955409065L);
124
+ testToParse("23:24:25", "%H:%M:%S", 81955409065L);
125
+ testToParse(" 32425", "%k%M%S", 81955337065L);
126
+ testToParse(" 32425", "%l%M%S", 81955337065L);
127
+
128
+ // They are intentionally skipped as a month and a day of week are not sufficient to build a timestamp.
129
+ // [['FriAug', '%a%b'], [nil,8,nil,nil,nil,nil,nil,nil,5], __LINE__],
130
+ // [['FriAug', '%A%B'], [nil,8,nil,nil,nil,nil,nil,nil,5], __LINE__],
131
+ // [['FridayAugust', '%A%B'], [nil,8,nil,nil,nil,nil,nil,nil,5], __LINE__],
132
+ // [['FridayAugust', '%a%b'], [nil,8,nil,nil,nil,nil,nil,nil,5], __LINE__],
133
+ }
134
+
135
+ @Test // Imported from test__strptime__fail in Ruby v2.3.1's test/date/test_date_strptime.rb.
136
+ public void test__strptime__fail() {
137
+ testToParse("2001.", "%Y.", 980208000L);
138
+ // Its " " is actually "\s" in Ruby v2.3.1's tests. "\s" is not recognized as a character in Java.
139
+ testToParse("2001. ", "%Y.", 980208000L);
140
+ testToParse("2001.", "%Y. ", 980208000L);
141
+ // Its " " is actually "\s" in Ruby v2.3.1's tests. "\s" is not recognized as a character in Java.
142
+ testToParse("2001. ", "%Y. ", 980208000L);
143
+
144
+ failToParse("2001", "%Y.");
145
+ // Its " " is actually "\s" in Ruby v2.3.1's tests. "\s" is not recognized as a character in Java.
146
+ failToParse("2001 ", "%Y.");
147
+ failToParse("2001", "%Y. ");
148
+ // Its " " is actually "\s" in Ruby v2.3.1's tests. "\s" is not recognized as a character in Java.
149
+ failToParse("2001 ", "%Y. ");
150
+
151
+ failToParse("2001-13-31", "%Y-%m-%d");
152
+ failToParse("2001-12-00", "%Y-%m-%d");
153
+ failToParse("2001-12-32", "%Y-%m-%d");
154
+ failToParse("2001-12-00", "%Y-%m-%e");
155
+ failToParse("2001-12-32", "%Y-%m-%e");
156
+ failToParse("2001-12-31", "%y-%m-%d");
157
+
158
+ failToParse("2004-000", "%Y-%j");
159
+ failToParse("2004-367", "%Y-%j");
160
+ failToParse("2004-366", "%y-%j");
161
+
162
+ testToParse("24:59:59", "%H:%M:%S", 81955414799L);
163
+ testToParse("24:59:59", "%k:%M:%S", 81955414799L);
164
+ testToParse("24:59:60", "%H:%M:%S", 81955414799L);
165
+ testToParse("24:59:60", "%k:%M:%S", 81955414799L);
166
+
167
+ failToParse("24:60:59", "%H:%M:%S");
168
+ failToParse("24:60:59", "%k:%M:%S");
169
+ failToParse("24:59:61", "%H:%M:%S");
170
+ failToParse("24:59:61", "%k:%M:%S");
171
+ failToParse("00:59:59", "%I:%M:%S");
172
+ failToParse("13:59:59", "%I:%M:%S");
173
+ failToParse("00:59:59", "%l:%M:%S");
174
+ failToParse("13:59:59", "%l:%M:%S");
175
+
176
+ testToParse("0", "%U", 81955324800L);
177
+ failToParse("54", "%U");
178
+ testToParse("0", "%W", 81955324800L);
179
+ failToParse("54", "%W");
180
+ failToParse("0", "%V");
181
+ failToParse("54", "%V");
182
+ failToParse("0", "%u");
183
+ testToParse("7", "%u", 81955324800L);
184
+ testToParse("0", "%w", 81955324800L);
185
+ failToParse("7", "%w");
186
+
187
+ failToParse("Sanday", "%A");
188
+ failToParse("Jenuary", "%B");
189
+ testToParse("Sundai", "%A", 81955324800L);
190
+ testToParse("Januari", "%B", 81955324800L);
191
+ failToParse("Sundai,", "%A,");
192
+ failToParse("Januari,", "%B,");
193
+ }
194
+
195
+ @Test // Imported partially from test_strptime in Ruby v2.3.1's test/date/test_date_strptime.rb.
196
+ public void test_strptime() {
197
+ testToParse("2002-03-14T11:22:33Z", "%Y-%m-%dT%H:%M:%S%Z", 1016104953L);
198
+ testToParse("2002-03-14T11:22:33+09:00", "%Y-%m-%dT%H:%M:%S%Z", 1016072553L);
199
+ testToParse("2002-03-14T11:22:33-09:00", "%FT%T%Z", 1016137353L);
200
+ testToParse("2002-03-14T11:22:33.123456789-09:00", "%FT%T.%N%Z", 1016137353L, 123456789);
201
+ }
202
+
203
+ @Test // Imported from test_strptime__minus in Ruby v2.3.1's test/date/test_date_strptime.rb.
204
+ public void test_strptime__minus() {
205
+ testToParse("-1", "%s", -1L);
206
+ testToParse("-86400", "%s", -86400L);
207
+
208
+ testToParse("-999", "%Q", 0L, -999000000);
209
+ testToParse("-1000", "%Q", -1L);
210
+ }
211
+
212
+ private void testToParse(final String string, final String format, final long second, final int nanoOfSecond) {
213
+ final TimestampParser parser = new TimestampParser(format, DateTimeZone.UTC, "4567-01-23");
214
+ final Timestamp timestamp = parser.parse(string);
215
+ assertEquals(second, timestamp.getEpochSecond());
216
+ assertEquals(nanoOfSecond,timestamp.getNano());
217
+ }
218
+
219
+ private void testToParse(final String string, final String format, final long second) {
220
+ testToParse(string, format, second, 0);
221
+ }
222
+
223
+ private void failToParse(final String string, final String format) {
224
+ final TimestampParser parser = new TimestampParser(format, DateTimeZone.UTC, "4567-01-23");
225
+ try {
226
+ parser.parse(string);
227
+ } catch (TimestampParseException ex) {
228
+ return;
229
+ }
230
+ fail();
231
+ }
232
+ }
@@ -4,6 +4,7 @@ Release Notes
4
4
  .. toctree::
5
5
  :maxdepth: 1
6
6
 
7
+ release/release-0.8.37
7
8
  release/release-0.8.36
8
9
  release/release-0.8.35
9
10
  release/release-0.8.34
@@ -0,0 +1,20 @@
1
+ Release 0.8.37
2
+ ==================================
3
+
4
+ General Changes
5
+ ----------------
6
+
7
+ * Parse Ruby-style time zone names in addition [#833] [#840]
8
+ * Remove dead code around the Ruby timestamp parser replaced [#813] [#823]
9
+
10
+ Bug Fixes
11
+ ----------
12
+
13
+ * Fix parsing leap seconds to get the same Timestamp with pure Ruby's [#842]
14
+ * Process yday (day of the year) in TimestampParser as well [#834] [#843]
15
+ * Fix nanoseconds set by StrptimeParser's %Q [#848]
16
+
17
+
18
+ Release Date
19
+ ------------------
20
+ 2017-11-21
@@ -36,7 +36,7 @@ enum StrptimeFormat
36
36
  FORMAT_NANOSEC, // %N
37
37
  FORMAT_MERIDIAN_LOWER_CASE, // %P
38
38
  FORMAT_MERIDIAN, // %p
39
- FORMAT_MICROSEC_EPOCH, // %Q Only for Date/DateTime from here
39
+ FORMAT_MILLISEC_EPOCH, // %Q Only for Date/DateTime from here
40
40
  FORMAT_SECONDS, // %S
41
41
  FORMAT_EPOCH, // %s
42
42
  FORMAT_WEEK_YEAR_S, // %U
@@ -576,7 +576,7 @@ public class StrptimeParser
576
576
  }
577
577
  break;
578
578
  }
579
- case FORMAT_MICROSEC_EPOCH: { // %Q - Number of microseconds since 1970-01-01 00:00:00 UTC.
579
+ case FORMAT_MILLISEC_EPOCH: { // %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC.
580
580
  boolean negative = false;
581
581
  if (isMinus(text, pos)) {
582
582
  negative = true;
@@ -39,7 +39,7 @@ public class StrptimeToken
39
39
  CONVERSION2TOKEN['N'] = new StrptimeToken(FORMAT_NANOSEC);
40
40
  CONVERSION2TOKEN['P'] = new StrptimeToken(FORMAT_MERIDIAN_LOWER_CASE);
41
41
  CONVERSION2TOKEN['p'] = new StrptimeToken(FORMAT_MERIDIAN);
42
- CONVERSION2TOKEN['Q'] = new StrptimeToken(FORMAT_MICROSEC_EPOCH);
42
+ CONVERSION2TOKEN['Q'] = new StrptimeToken(FORMAT_MILLISEC_EPOCH);
43
43
  CONVERSION2TOKEN['S'] = new StrptimeToken(FORMAT_SECONDS);
44
44
  CONVERSION2TOKEN['s'] = new StrptimeToken(FORMAT_EPOCH);
45
45
  CONVERSION2TOKEN['U'] = new StrptimeToken(FORMAT_WEEK_YEAR_S);
@@ -1,7 +1,7 @@
1
1
  module Embulk
2
2
  module Java
3
3
  require 'embulk/java/imports'
4
- require 'embulk/java/time_helper'
4
+ require 'time'
5
5
 
6
6
  module Injected
7
7
  # Following constats are set by org.embulk.jruby.JRubyScriptingModule:
@@ -3,7 +3,7 @@
3
3
  module Embulk
4
4
  @@warned = false
5
5
 
6
- VERSION_INTERNAL = '0.8.36'
6
+ VERSION_INTERNAL = '0.8.37'
7
7
 
8
8
  DEPRECATED_MESSAGE = 'Embulk::VERSION in (J)Ruby is deprecated. Use org.embulk.EmbulkVersion::VERSION instead. If this message is from a plugin, please tell this to the author of the plugin!'
9
9
  def self.const_missing(name)
@@ -1,10 +1,11 @@
1
- base_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
1
+ base_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
2
2
  lib_dir = File.join(base_dir, "lib")
3
3
  test_dir = File.join(base_dir, "test")
4
4
 
5
5
  $LOAD_PATH.unshift(lib_dir)
6
6
  $LOAD_PATH.unshift(test_dir)
7
7
 
8
+ require "helper"
8
9
  require "date"
9
10
  require "test/unit"
10
11
 
@@ -21,7 +22,7 @@ module DateExt
21
22
  end
22
23
  Date.send(:include, DateExt)
23
24
 
24
- Dir.glob("#{base_dir}/test/**/test{_,-}*.rb") do |file|
25
+ Dir.glob("#{base_dir}/test/monkey_strptime/**/test{_,-}*.rb") do |file|
25
26
  require file.sub(/\.rb$/,"")
26
27
  end
27
28
 
@@ -0,0 +1,14 @@
1
+ base_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
2
+ lib_dir = File.join(base_dir, "lib")
3
+ test_dir = File.join(base_dir, "test")
4
+
5
+ $LOAD_PATH.unshift(lib_dir)
6
+ $LOAD_PATH.unshift(test_dir)
7
+
8
+ require "test/unit"
9
+
10
+ Dir.glob("#{base_dir}/test/vanilla/**/test{_,-}*.rb") do |file|
11
+ require file.sub(/\.rb$/,"")
12
+ end
13
+
14
+ exit Test::Unit::AutoRunner.run
@@ -0,0 +1,102 @@
1
+ require 'helper'
2
+ require 'date'
3
+ require 'time'
4
+
5
+ # TimestampParserTest test org.embulk.spi.time.TimestampParser by comparing with Ruby's DateTime.strptime.
6
+ #
7
+ # Some test cases are imported from Ruby v2.3.1's test/date/test_date_strptime.rb. See its COPYING for license.
8
+ #
9
+ # *{test/date/test_date_strptime.rb}[https://svn.ruby-lang.org/cgi-bin/viewvc.cgi/tags/v2_3_1/test/date/test_date_strptime.rb?view=markup]
10
+ # *{COPYING}[https://svn.ruby-lang.org/cgi-bin/viewvc.cgi/tags/v2_3_1/COPYING?view=markup]
11
+
12
+ class TimestampParserTest < ::Test::Unit::TestCase
13
+ def test__strptime__3
14
+ [
15
+ # iso8601
16
+ ['2001-02-03', '%Y-%m-%d'],
17
+ ['2001-02-03T23:59:60', '%Y-%m-%dT%H:%M:%S'],
18
+ ['2001-02-03T23:59:60+09:00', '%Y-%m-%dT%H:%M:%S%Z'],
19
+ ['-2001-02-03T23:59:60+09:00', '%Y-%m-%dT%H:%M:%S%Z'],
20
+ ['+012345-02-03T23:59:60+09:00', '%Y-%m-%dT%H:%M:%S%Z'],
21
+ ['-012345-02-03T23:59:60+09:00', '%Y-%m-%dT%H:%M:%S%Z'],
22
+
23
+ # ctime(3), asctime(3)
24
+ ['Thu Jul 29 14:47:19 1999', '%c'],
25
+ ['Thu Jul 29 14:47:19 -1999', '%c'],
26
+
27
+ # date(1)
28
+ ['Thu Jul 29 16:39:41 EST 1999', '%a %b %d %H:%M:%S %Z %Y'],
29
+ ['Thu Jul 29 16:39:41 MET DST 1999', '%a %b %d %H:%M:%S %Z %Y'],
30
+ # Their time zones are "AMT" actually in Ruby v2.3.1's tests, but "AST" is used here instead.
31
+ # "AMT" is not recognized even by Ruby v2.3.1's zonetab.
32
+ ['Thu Jul 29 16:39:41 AST 1999', '%a %b %d %H:%M:%S %Z %Y'],
33
+ ['Thu Jul 29 16:39:41 AST -1999', '%a %b %d %H:%M:%S %Z %Y'],
34
+ ['Thu Jul 29 16:39:41 GMT+09 1999', '%a %b %d %H:%M:%S %Z %Y'],
35
+ ['Thu Jul 29 16:39:41 GMT+0908 1999', '%a %b %d %H:%M:%S %Z %Y'],
36
+ ['Thu Jul 29 16:39:41 GMT+090807 1999', '%a %b %d %H:%M:%S %Z %Y'],
37
+ ['Thu Jul 29 16:39:41 GMT-09 1999', '%a %b %d %H:%M:%S %Z %Y'],
38
+ ['Thu Jul 29 16:39:41 GMT-09:08 1999', '%a %b %d %H:%M:%S %Z %Y'],
39
+ ['Thu Jul 29 16:39:41 GMT-09:08:07 1999', '%a %b %d %H:%M:%S %Z %Y'],
40
+ ['Thu Jul 29 16:39:41 GMT-3.5 1999', '%a %b %d %H:%M:%S %Z %Y'],
41
+ ['Thu Jul 29 16:39:41 GMT-3,5 1999', '%a %b %d %H:%M:%S %Z %Y'],
42
+ ['Thu Jul 29 16:39:41 Mountain Daylight Time 1999', '%a %b %d %H:%M:%S %Z %Y'],
43
+ ['Thu Jul 29 16:39:41 E. Australia Standard Time 1999', '%a %b %d %H:%M:%S %Z %Y'],
44
+
45
+ # rfc822
46
+ ['Thu, 29 Jul 1999 09:54:21 UT', '%a, %d %b %Y %H:%M:%S %Z'],
47
+ ['Thu, 29 Jul 1999 09:54:21 GMT', '%a, %d %b %Y %H:%M:%S %Z'],
48
+ ['Thu, 29 Jul 1999 09:54:21 PDT', '%a, %d %b %Y %H:%M:%S %Z'],
49
+ ['Thu, 29 Jul 1999 09:54:21 z', '%a, %d %b %Y %H:%M:%S %Z'],
50
+ ['Thu, 29 Jul 1999 09:54:21 +0900', '%a, %d %b %Y %H:%M:%S %Z'],
51
+ ['Thu, 29 Jul 1999 09:54:21 +0430', '%a, %d %b %Y %H:%M:%S %Z'],
52
+ ['Thu, 29 Jul 1999 09:54:21 -0430', '%a, %d %b %Y %H:%M:%S %Z'],
53
+ ['Thu, 29 Jul -1999 09:54:21 -0430', '%a, %d %b %Y %H:%M:%S %Z'],
54
+
55
+ # etc
56
+ ['06-DEC-99', '%d-%b-%y'],
57
+ ['sUnDay oCtoBer 31 01', '%A %B %d %y'],
58
+ ["October\t\n\v\f\r 15,\t\n\v\f\r99", '%B %d, %y'],
59
+ ["October\t\n\v\f\r 15,\t\n\v\f\r99", '%B%t%d,%n%y'],
60
+
61
+ ['09:02:11 AM', '%I:%M:%S %p'],
62
+ ['09:02:11 A.M.', '%I:%M:%S %p'],
63
+ ['09:02:11 PM', '%I:%M:%S %p'],
64
+ ['09:02:11 P.M.', '%I:%M:%S %p'],
65
+
66
+ ['12:33:44 AM', '%r'],
67
+ ['01:33:44 AM', '%r'],
68
+ ['11:33:44 AM', '%r'],
69
+ ['12:33:44 PM', '%r'],
70
+ ['01:33:44 PM', '%r'],
71
+ ['11:33:44 PM', '%r'],
72
+
73
+ # Their time zones are "AMT" actually in Ruby v2.3.1's tests, but "AST" is used here instead.
74
+ # "AMT" is not recognized even by Ruby v2.3.1's zonetab.
75
+ ['11:33:44 PM AST', '%I:%M:%S %p %Z'],
76
+ ['11:33:44 P.M. AST', '%I:%M:%S %p %Z'],
77
+
78
+ ['fri1feb034pm+5', '%a%d%b%y%H%p%Z'],
79
+ ].each do |string, format|
80
+ before_date = Date.today
81
+ after_date = nil
82
+ while before_date != after_date do
83
+ before_date = Date.today
84
+ expected_datetime = DateTime.strptime(string, format)
85
+ expected_time = expected_datetime.new_offset(0).to_time.utc
86
+ after_date = Date.today
87
+ if expected_datetime.to_date == after_date # DateTime.strptime fills today's date if date is not contained.
88
+ # Getting the Time of 00:00:00 UTC on after_date.
89
+ expected_time = expected_time - after_date.to_datetime.new_offset(0).to_time.utc
90
+ end
91
+ expected_epoch = expected_time.to_i
92
+ end
93
+
94
+ timestamp_parser =
95
+ Java::org.embulk.spi.time.TimestampParser.new(format, Java::org.joda.time.DateTimeZone::UTC, "1970-01-01")
96
+ actual_timestamp = timestamp_parser.parse(string)
97
+ actual_epoch = actual_timestamp.getEpochSecond()
98
+
99
+ assert_equal(expected_epoch, actual_epoch, string)
100
+ end
101
+ end
102
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.36
4
+ version: 0.8.37
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-24 00:00:00.000000000 Z
11
+ date: 2017-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jruby-jars
@@ -115,10 +115,10 @@ files:
115
115
  - classpath/commons-compress-1.10.jar
116
116
  - classpath/commons-lang-2.4.jar
117
117
  - classpath/commons-lang3-3.4.jar
118
- - classpath/embulk-cli-0.8.36.jar
119
- - classpath/embulk-core-0.8.36.jar
120
- - classpath/embulk-jruby-strptime-0.8.36.jar
121
- - classpath/embulk-standards-0.8.36.jar
118
+ - classpath/embulk-cli-0.8.37.jar
119
+ - classpath/embulk-core-0.8.37.jar
120
+ - classpath/embulk-jruby-strptime-0.8.37.jar
121
+ - classpath/embulk-standards-0.8.37.jar
122
122
  - classpath/guava-18.0.jar
123
123
  - classpath/guice-4.0.jar
124
124
  - classpath/guice-bootstrap-0.1.1.jar
@@ -306,8 +306,6 @@ files:
306
306
  - embulk-core/src/main/java/org/embulk/spi/json/JsonParser.java
307
307
  - embulk-core/src/main/java/org/embulk/spi/json/RubyValueApi.java
308
308
  - embulk-core/src/main/java/org/embulk/spi/time/DateTimeZoneSerDe.java
309
- - embulk-core/src/main/java/org/embulk/spi/time/JRubyTimeParserHelper.java
310
- - embulk-core/src/main/java/org/embulk/spi/time/JRubyTimeParserHelperFactory.java
311
309
  - embulk-core/src/main/java/org/embulk/spi/time/Timestamp.java
312
310
  - embulk-core/src/main/java/org/embulk/spi/time/TimestampFormat.java
313
311
  - embulk-core/src/main/java/org/embulk/spi/time/TimestampFormatter.java
@@ -397,6 +395,7 @@ files:
397
395
  - embulk-core/src/test/java/org/embulk/spi/time/TestTimestamp.java
398
396
  - embulk-core/src/test/java/org/embulk/spi/time/TestTimestampFormatterParser.java
399
397
  - embulk-core/src/test/java/org/embulk/spi/time/TestTimestampFormatterParserDeprecated.java
398
+ - embulk-core/src/test/java/org/embulk/spi/time/TestTimestampParser.java
400
399
  - embulk-core/src/test/java/org/embulk/spi/type/TestTypeSerDe.java
401
400
  - embulk-core/src/test/java/org/embulk/spi/unit/TestByteSize.java
402
401
  - embulk-core/src/test/java/org/embulk/spi/util/TestLineDecoder.java
@@ -526,6 +525,7 @@ files:
526
525
  - embulk-docs/src/release/release-0.8.34.rst
527
526
  - embulk-docs/src/release/release-0.8.35.rst
528
527
  - embulk-docs/src/release/release-0.8.36.rst
528
+ - embulk-docs/src/release/release-0.8.37.rst
529
529
  - embulk-docs/src/release/release-0.8.4.rst
530
530
  - embulk-docs/src/release/release-0.8.5.rst
531
531
  - embulk-docs/src/release/release-0.8.6.rst
@@ -740,7 +740,6 @@ files:
740
740
  - lib/embulk/input_plugin.rb
741
741
  - lib/embulk/java/bootstrap.rb
742
742
  - lib/embulk/java/imports.rb
743
- - lib/embulk/java/time_helper.rb
744
743
  - lib/embulk/java_plugin.rb
745
744
  - lib/embulk/logger.rb
746
745
  - lib/embulk/output_plugin.rb
@@ -753,13 +752,15 @@ files:
753
752
  - lib/embulk/schema.rb
754
753
  - lib/embulk/version.rb
755
754
  - settings.gradle
756
- - test/guess/test_csv_all_strings.rb
757
- - test/guess/test_csv_guess.rb
758
- - test/guess/test_schema_guess.rb
759
- - test/guess/test_time_format_guess.rb
760
755
  - test/helper.rb
761
- - test/mri/date/test_date_strptime.rb
762
- - test/run-test.rb
756
+ - test/monkey_strptime/mri/date/test_date_strptime.rb
757
+ - test/monkey_strptime/run-test.rb
758
+ - test/vanilla/guess/test_csv_all_strings.rb
759
+ - test/vanilla/guess/test_csv_guess.rb
760
+ - test/vanilla/guess/test_schema_guess.rb
761
+ - test/vanilla/guess/test_time_format_guess.rb
762
+ - test/vanilla/run-test.rb
763
+ - test/vanilla/time/test_timestamp_parser.rb
763
764
  homepage: https://github.com/embulk/embulk
764
765
  licenses:
765
766
  - Apache 2.0
@@ -785,10 +786,12 @@ signing_key:
785
786
  specification_version: 4
786
787
  summary: Embulk, a plugin-based parallel bulk data loader
787
788
  test_files:
788
- - test/guess/test_csv_all_strings.rb
789
- - test/guess/test_csv_guess.rb
790
- - test/guess/test_schema_guess.rb
791
- - test/guess/test_time_format_guess.rb
792
789
  - test/helper.rb
793
- - test/mri/date/test_date_strptime.rb
794
- - test/run-test.rb
790
+ - test/monkey_strptime/mri/date/test_date_strptime.rb
791
+ - test/monkey_strptime/run-test.rb
792
+ - test/vanilla/guess/test_csv_all_strings.rb
793
+ - test/vanilla/guess/test_csv_guess.rb
794
+ - test/vanilla/guess/test_schema_guess.rb
795
+ - test/vanilla/guess/test_time_format_guess.rb
796
+ - test/vanilla/run-test.rb
797
+ - test/vanilla/time/test_timestamp_parser.rb
@@ -1,8 +0,0 @@
1
- package org.embulk.spi.time;
2
-
3
- public interface JRubyTimeParserHelper
4
- {
5
- long strptimeUsec(String text) throws TimestampParseException;
6
-
7
- String getZone();
8
- }
@@ -1,6 +0,0 @@
1
- package org.embulk.spi.time;
2
-
3
- public interface JRubyTimeParserHelperFactory
4
- {
5
- JRubyTimeParserHelper newInstance(String formatString, int year, int mon, int day, int hour, int min, int sec, int usec);
6
- }
@@ -1,79 +0,0 @@
1
- module Embulk
2
- module Java
3
- #require 'embulk/java/imports'
4
- require 'time' # Date._strptime
5
-
6
- class TimeParserHelper
7
- #include Java::JRubyTimeParserHelper
8
- include org.embulk.spi.time.JRubyTimeParserHelper
9
-
10
- class Factory
11
- #include Java::JRubyTimeParserHelperFactory
12
- include org.embulk.spi.time.JRubyTimeParserHelperFactory
13
-
14
- def newInstance(format_string, year, mon, day, hour, min, sec, usec)
15
- default_time = Time.utc(year, mon, day, hour, min, sec, usec)
16
- TimeParserHelper.new(format_string, default_time)
17
- end
18
- end
19
-
20
- def initialize(format_string, default_time)
21
- @format_string = format_string
22
- @default_time = default_time
23
- end
24
-
25
- # Override
26
- def strptimeUsec(text)
27
- hash = Date._strptime(text, @format_string)
28
- unless hash
29
- raise Java::TimestampParseException.new("Failed to parse '" + text + "'")
30
- end
31
-
32
- if seconds = hash[:seconds] # if %s, it's Integer. if %Q, Rational.
33
- sec_fraction = hash[:sec_fraction] # Rational
34
- usec = sec_fraction * 1_000_000 if sec_fraction
35
- return (seconds * 1_000_000).to_i + usec.to_i
36
-
37
- else
38
- year = hash[:year]
39
- mon = hash[:mon]
40
- day = hash[:mday]
41
- hour = hash[:hour]
42
- min = hash[:min]
43
- sec = hash[:sec]
44
- sec_fraction = hash[:sec_fraction]
45
- usec = sec_fraction * 1_000_000 if sec_fraction
46
- zone = hash[:zone]
47
-
48
- now = @default_time
49
- begin
50
- break if year; year = now.year
51
- break if mon; mon = now.mon
52
- break if day; day = now.day
53
- break if hour; hour = now.hour
54
- break if min; min = now.min
55
- break if sec; sec = now.sec
56
- break if sec_fraction; usec = now.tv_usec
57
- end until true
58
-
59
- year ||= 1970
60
- mon ||= 1
61
- day ||= 1
62
- hour ||= 0
63
- min ||= 0
64
- sec ||= 0
65
- usec ||= 0
66
-
67
- @zone = zone
68
- time = Time.utc(year, mon, day, hour, min, sec, usec)
69
- return time.tv_sec * 1_000_000 + time.tv_usec
70
- end
71
- end
72
-
73
- # Override
74
- def getZone
75
- @zone
76
- end
77
- end
78
- end
79
- end