embulk 0.8.36 → 0.8.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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