embulk 0.1.0
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 +15 -0
- data/.gitignore +13 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +33 -0
- data/README.md +117 -0
- data/Rakefile +58 -0
- data/bin/embulk +63 -0
- data/build.gradle +149 -0
- data/embulk-cli/build.gradle +6 -0
- data/embulk-cli/pom.xml +94 -0
- data/embulk-cli/src/main/java/org/embulk/cli/Main.java +15 -0
- data/embulk-core/build.gradle +6 -0
- data/embulk-core/pom.xml +143 -0
- data/embulk-core/src/main/java/org/embulk/EmbulkService.java +39 -0
- data/embulk-core/src/main/java/org/embulk/command/Runner.java +199 -0
- data/embulk-core/src/main/java/org/embulk/command/TablePrinter.java +119 -0
- data/embulk-core/src/main/java/org/embulk/config/CommitReport.java +26 -0
- data/embulk-core/src/main/java/org/embulk/config/Config.java +15 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigDefault.java +15 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigException.java +20 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigLoader.java +83 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigSource.java +28 -0
- data/embulk-core/src/main/java/org/embulk/config/DataSource.java +35 -0
- data/embulk-core/src/main/java/org/embulk/config/DataSourceImpl.java +208 -0
- data/embulk-core/src/main/java/org/embulk/config/DataSourceSerDe.java +80 -0
- data/embulk-core/src/main/java/org/embulk/config/GenericTypeReference.java +20 -0
- data/embulk-core/src/main/java/org/embulk/config/ModelManager.java +125 -0
- data/embulk-core/src/main/java/org/embulk/config/NextConfig.java +26 -0
- data/embulk-core/src/main/java/org/embulk/config/Task.java +10 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskInvocationHandler.java +180 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskSerDe.java +343 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskSource.java +28 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskValidationException.java +37 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskValidator.java +24 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExecModule.java +45 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExecuteInterruptedException.java +10 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExecuteResult.java +19 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExtensionServiceLoaderModule.java +43 -0
- data/embulk-core/src/main/java/org/embulk/exec/ForSystemConfig.java +16 -0
- data/embulk-core/src/main/java/org/embulk/exec/GuessExecutor.java +307 -0
- data/embulk-core/src/main/java/org/embulk/exec/LocalExecutor.java +274 -0
- data/embulk-core/src/main/java/org/embulk/exec/LoggerProvider.java +30 -0
- data/embulk-core/src/main/java/org/embulk/exec/NoSampleException.java +10 -0
- data/embulk-core/src/main/java/org/embulk/exec/PooledBufferAllocator.java +58 -0
- data/embulk-core/src/main/java/org/embulk/exec/PreviewExecutor.java +138 -0
- data/embulk-core/src/main/java/org/embulk/exec/PreviewResult.java +27 -0
- data/embulk-core/src/main/java/org/embulk/exec/PreviewedNoticeError.java +17 -0
- data/embulk-core/src/main/java/org/embulk/exec/SamplingParserPlugin.java +116 -0
- data/embulk-core/src/main/java/org/embulk/exec/SystemConfigModule.java +24 -0
- data/embulk-core/src/main/java/org/embulk/jruby/JRubyPluginSource.java +69 -0
- data/embulk-core/src/main/java/org/embulk/jruby/JRubyScriptingModule.java +100 -0
- data/embulk-core/src/main/java/org/embulk/plugin/BuiltinPluginSourceModule.java +17 -0
- data/embulk-core/src/main/java/org/embulk/plugin/InjectedPluginSource.java +92 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginManager.java +34 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginSource.java +6 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginSourceNotMatchException.java +19 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginType.java +47 -0
- data/embulk-core/src/main/java/org/embulk/plugin/SetThreadContextClassLoader.java +19 -0
- data/embulk-core/src/main/java/org/embulk/spi/Buffer.java +113 -0
- data/embulk-core/src/main/java/org/embulk/spi/BufferAllocator.java +8 -0
- data/embulk-core/src/main/java/org/embulk/spi/Column.java +92 -0
- data/embulk-core/src/main/java/org/embulk/spi/ColumnConfig.java +79 -0
- data/embulk-core/src/main/java/org/embulk/spi/DecoderPlugin.java +16 -0
- data/embulk-core/src/main/java/org/embulk/spi/EncoderPlugin.java +16 -0
- data/embulk-core/src/main/java/org/embulk/spi/Exec.java +76 -0
- data/embulk-core/src/main/java/org/embulk/spi/ExecAction.java +6 -0
- data/embulk-core/src/main/java/org/embulk/spi/ExecSession.java +105 -0
- data/embulk-core/src/main/java/org/embulk/spi/Extension.java +42 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileInput.java +11 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileInputPlugin.java +19 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileInputRunner.java +113 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileOutput.java +13 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileOutputPlugin.java +20 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileOutputRunner.java +167 -0
- data/embulk-core/src/main/java/org/embulk/spi/FormatterPlugin.java +18 -0
- data/embulk-core/src/main/java/org/embulk/spi/GuessPlugin.java +9 -0
- data/embulk-core/src/main/java/org/embulk/spi/InputPlugin.java +20 -0
- data/embulk-core/src/main/java/org/embulk/spi/OutputPlugin.java +21 -0
- data/embulk-core/src/main/java/org/embulk/spi/Page.java +45 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageBuilder.java +327 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageFormat.java +47 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageOutput.java +11 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageReader.java +227 -0
- data/embulk-core/src/main/java/org/embulk/spi/ParserPlugin.java +17 -0
- data/embulk-core/src/main/java/org/embulk/spi/Schema.java +101 -0
- data/embulk-core/src/main/java/org/embulk/spi/SchemaConfig.java +52 -0
- data/embulk-core/src/main/java/org/embulk/spi/SchemaVisitor.java +14 -0
- data/embulk-core/src/main/java/org/embulk/spi/Transactional.java +10 -0
- data/embulk-core/src/main/java/org/embulk/spi/TransactionalFileInput.java +17 -0
- data/embulk-core/src/main/java/org/embulk/spi/TransactionalFileOutput.java +19 -0
- data/embulk-core/src/main/java/org/embulk/spi/TransactionalPageOutput.java +17 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/DateTimeZoneSerDe.java +57 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/JRubyTimeParserHelper.java +8 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/JRubyTimeParserHelperFactory.java +6 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/Timestamp.java +159 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampFormat.java +98 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampFormatter.java +55 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampParseException.java +6 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampParser.java +60 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampSerDe.java +50 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/AbstractType.java +55 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/BooleanType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/DoubleType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/LongType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/StringType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/TimestampType.java +39 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/Type.java +15 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/TypeDeserializer.java +47 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/Types.java +14 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/CharsetSerDe.java +55 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Decoders.java +81 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Encoders.java +81 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/FileInputInputStream.java +110 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/FileOutputOutputStream.java +94 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/InputStreamFileInput.java +111 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Inputs.java +74 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/LineDecoder.java +118 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/LineEncoder.java +109 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/ListFileInput.java +52 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Newline.java +38 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/PagePrinter.java +102 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Pages.java +139 -0
- data/embulk-core/src/test/java/org/embulk/EmbulkTestRuntime.java +110 -0
- data/embulk-core/src/test/java/org/embulk/GuiceBinder.java +72 -0
- data/embulk-core/src/test/java/org/embulk/RandomManager.java +53 -0
- data/embulk-core/src/test/java/org/embulk/TestPluginSourceModule.java +23 -0
- data/embulk-core/src/test/java/org/embulk/TestUtilityModule.java +17 -0
- data/embulk-core/src/test/java/org/embulk/config/TestConfigSource.java +114 -0
- data/embulk-core/src/test/java/org/embulk/config/TestTaskSource.java +70 -0
- data/embulk-core/src/test/java/org/embulk/plugin/MockPluginSource.java +57 -0
- data/embulk-core/src/test/java/org/embulk/plugin/TestPluginType.java +18 -0
- data/embulk-core/src/test/java/org/embulk/spi/MockFileOutput.java +63 -0
- data/embulk-core/src/test/java/org/embulk/spi/MockFormatterPlugin.java +101 -0
- data/embulk-core/src/test/java/org/embulk/spi/MockParserPlugin.java +73 -0
- data/embulk-core/src/test/java/org/embulk/spi/PageTestUtils.java +78 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestFileInputInputStream.java +67 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestFileInputRunner.java +180 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestFileOutputRunner.java +192 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestInputStreamFileInput.java +188 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestPageBuilderReader.java +301 -0
- data/embulk-core/src/test/java/org/embulk/spi/time/TestTimestamp.java +116 -0
- data/embulk-core/src/test/java/org/embulk/spi/time/TestTimestampFormatterParser.java +52 -0
- data/embulk-core/src/test/java/org/embulk/spi/type/TestTypeSerDe.java +45 -0
- data/embulk-core/src/test/java/org/embulk/spi/util/TestLineDecoder.java +132 -0
- data/embulk-core/src/test/java/org/embulk/spi/util/TestLineEncoder.java +123 -0
- data/embulk-standards/build.gradle +6 -0
- data/embulk-standards/pom.xml +68 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvFormatterPlugin.java +158 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvParserPlugin.java +233 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvTokenizer.java +355 -0
- data/embulk-standards/src/main/java/org/embulk/standards/GzipFileDecoderPlugin.java +55 -0
- data/embulk-standards/src/main/java/org/embulk/standards/GzipFileEncoderPlugin.java +39 -0
- data/embulk-standards/src/main/java/org/embulk/standards/LocalFileInputPlugin.java +138 -0
- data/embulk-standards/src/main/java/org/embulk/standards/LocalFileOutputPlugin.java +128 -0
- data/embulk-standards/src/main/java/org/embulk/standards/NullOutputPlugin.java +46 -0
- data/embulk-standards/src/main/java/org/embulk/standards/S3FileInputPlugin.java +238 -0
- data/embulk-standards/src/main/java/org/embulk/standards/StandardPluginExtension.java +16 -0
- data/embulk-standards/src/main/java/org/embulk/standards/StandardPluginModule.java +44 -0
- data/embulk-standards/src/main/java/org/embulk/standards/StdoutOutputPlugin.java +71 -0
- data/embulk-standards/src/main/resources/META-INF/services/org.embulk.spi.Extension +1 -0
- data/embulk-standards/src/test/java/org/embulk/standards/TestCsvParserPlugin.java +69 -0
- data/embulk-standards/src/test/java/org/embulk/standards/TestCsvTokenizer.java +291 -0
- data/embulk-standards/src/test/java/org/embulk/standards/TestS3FileInputPlugin.java +43 -0
- data/embulk.gemspec +27 -0
- data/examples/config.yml +34 -0
- data/examples/csv/sample.csv.gz +0 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/gradlew +164 -0
- data/gradlew.bat +90 -0
- data/lib/embulk.rb +16 -0
- data/lib/embulk/buffer.rb +17 -0
- data/lib/embulk/column.rb +47 -0
- data/lib/embulk/command/embulk.rb +39 -0
- data/lib/embulk/command/embulk_example.rb +32 -0
- data/lib/embulk/command/embulk_generate_bin.rb +62 -0
- data/lib/embulk/command/embulk_run.rb +243 -0
- data/lib/embulk/data/bundle/.bundle/config +3 -0
- data/lib/embulk/data/bundle/Gemfile +31 -0
- data/lib/embulk/data/bundle/Gemfile.lock +8 -0
- data/lib/embulk/data/bundle/embulk/input_example.rb +40 -0
- data/lib/embulk/data/bundle/embulk/output_example.rb +51 -0
- data/lib/embulk/data_source.rb +66 -0
- data/lib/embulk/error.rb +5 -0
- data/lib/embulk/guess_charset.rb +26 -0
- data/lib/embulk/guess_csv.rb +195 -0
- data/lib/embulk/guess_gzip.rb +18 -0
- data/lib/embulk/guess_newline.rb +20 -0
- data/lib/embulk/guess_plugin.rb +113 -0
- data/lib/embulk/input_plugin.rb +53 -0
- data/lib/embulk/java/bootstrap.rb +12 -0
- data/lib/embulk/java/imports.rb +26 -0
- data/lib/embulk/java/time_helper.rb +77 -0
- data/lib/embulk/output_plugin.rb +104 -0
- data/lib/embulk/page.rb +28 -0
- data/lib/embulk/page_builder.rb +22 -0
- data/lib/embulk/plugin.rb +152 -0
- data/lib/embulk/plugin_registry.rb +70 -0
- data/lib/embulk/schema.rb +85 -0
- data/lib/embulk/time_format_guess.rb +331 -0
- data/lib/embulk/version.rb +3 -0
- data/pom.xml +533 -0
- data/settings.gradle +5 -0
- metadata +370 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
package org.embulk.spi.time;
|
|
2
|
+
|
|
3
|
+
import java.util.Set;
|
|
4
|
+
import java.util.Date;
|
|
5
|
+
import java.text.SimpleDateFormat;
|
|
6
|
+
import java.text.ParsePosition;
|
|
7
|
+
import com.google.common.collect.ImmutableSet;
|
|
8
|
+
import com.fasterxml.jackson.annotation.JsonValue;
|
|
9
|
+
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
10
|
+
import org.joda.time.DateTimeZone;
|
|
11
|
+
import org.joda.time.format.DateTimeFormat;
|
|
12
|
+
|
|
13
|
+
public class TimestampFormat
|
|
14
|
+
{
|
|
15
|
+
private final String format;
|
|
16
|
+
|
|
17
|
+
@JsonCreator
|
|
18
|
+
public TimestampFormat(String format)
|
|
19
|
+
{
|
|
20
|
+
this.format = format;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@JsonValue
|
|
24
|
+
public String getFormat()
|
|
25
|
+
{
|
|
26
|
+
return format;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public TimestampFormatter newFormatter(TimestampFormatter.FormatterTask task)
|
|
30
|
+
{
|
|
31
|
+
return new TimestampFormatter(format, task);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public TimestampParser newParser(TimestampParser.ParserTask task)
|
|
35
|
+
{
|
|
36
|
+
return new TimestampParser(format, task);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private static Set<String> availableTimeZoneNames = ImmutableSet.copyOf(DateTimeZone.getAvailableIDs());
|
|
40
|
+
|
|
41
|
+
public static DateTimeZone parseDateTimeZone(String s)
|
|
42
|
+
{
|
|
43
|
+
if(s.startsWith("+") || s.startsWith("-")) {
|
|
44
|
+
return DateTimeZone.forID("GMT"+s);
|
|
45
|
+
|
|
46
|
+
} else {
|
|
47
|
+
try {
|
|
48
|
+
int rawOffset = (int) DateTimeFormat.forPattern("z").parseMillis(s);
|
|
49
|
+
if(rawOffset == 0) {
|
|
50
|
+
return DateTimeZone.UTC;
|
|
51
|
+
}
|
|
52
|
+
int offset = rawOffset / -1000;
|
|
53
|
+
int h = offset / 3600;
|
|
54
|
+
int m = offset % 3600;
|
|
55
|
+
return DateTimeZone.forOffsetHoursMinutes(h, m);
|
|
56
|
+
} catch (IllegalArgumentException ex) {
|
|
57
|
+
// parseMillis failed
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// TimeZone.getTimeZone returns GMT zone if given timezone id is not found
|
|
61
|
+
// we want to only return timezone if exact match, otherwise exception
|
|
62
|
+
if (availableTimeZoneNames.contains(s)) {
|
|
63
|
+
//return TimeZone.getTimeZone(s);
|
|
64
|
+
return DateTimeZone.forID(s);
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//// Java standard TimeZone
|
|
71
|
+
//static TimeZone parseDateTimeZone(String s)
|
|
72
|
+
//{
|
|
73
|
+
// if(s.startsWith("+") || s.startsWith("-")) {
|
|
74
|
+
// return TimeZone.getTimeZone("GMT"+s);
|
|
75
|
+
//
|
|
76
|
+
// } else {
|
|
77
|
+
// ParsePosition pp = new ParsePosition(0);
|
|
78
|
+
// Date off = new SimpleDateFormat("z").parse(s, pp);
|
|
79
|
+
// if(off != null && pp.getErrorIndex() == -1) {
|
|
80
|
+
// int rawOffset = (int) off.getTime();
|
|
81
|
+
// if(rawOffset == 0) {
|
|
82
|
+
// return TimeZone.UTC;
|
|
83
|
+
// }
|
|
84
|
+
// int offset = rawOffset / -1000;
|
|
85
|
+
// int h = offset / 3600;
|
|
86
|
+
// int m = offset % 3600;
|
|
87
|
+
// return DateTimeZone.getTimeZone(String.format("GMT%+02d%02d", h, m));
|
|
88
|
+
// }
|
|
89
|
+
//
|
|
90
|
+
// // TimeZone.getTimeZone returns GMT zone if given timezone id is not found
|
|
91
|
+
// // we want to only return timezone if exact match, otherwise exception
|
|
92
|
+
// if (availableTimeZoneNames.contains(s)) {
|
|
93
|
+
// return TimeZone.getTimeZone(s);
|
|
94
|
+
// }
|
|
95
|
+
// return null;
|
|
96
|
+
// }
|
|
97
|
+
//}
|
|
98
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
package org.embulk.spi.time;
|
|
2
|
+
|
|
3
|
+
import java.util.Locale;
|
|
4
|
+
import org.joda.time.DateTime;
|
|
5
|
+
import org.joda.time.DateTimeZone;
|
|
6
|
+
import org.jruby.embed.ScriptingContainer;
|
|
7
|
+
import org.jruby.util.RubyDateFormat;
|
|
8
|
+
import com.fasterxml.jackson.annotation.JacksonInject;
|
|
9
|
+
import org.embulk.config.Task;
|
|
10
|
+
import org.embulk.config.Config;
|
|
11
|
+
import org.embulk.config.ConfigDefault;
|
|
12
|
+
import org.embulk.config.ConfigException;
|
|
13
|
+
import org.embulk.spi.util.LineEncoder;
|
|
14
|
+
|
|
15
|
+
public class TimestampFormatter
|
|
16
|
+
{
|
|
17
|
+
public interface FormatterTask
|
|
18
|
+
extends Task
|
|
19
|
+
{
|
|
20
|
+
@Config("timezone")
|
|
21
|
+
@ConfigDefault("\"UTC\"")
|
|
22
|
+
public DateTimeZone getTimeZone();
|
|
23
|
+
|
|
24
|
+
@JacksonInject
|
|
25
|
+
public ScriptingContainer getJRuby();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private final RubyDateFormat dateFormat;
|
|
29
|
+
private final DateTimeZone timeZone;
|
|
30
|
+
|
|
31
|
+
public TimestampFormatter(String format, FormatterTask task)
|
|
32
|
+
{
|
|
33
|
+
this(task.getJRuby(), format, task.getTimeZone());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public TimestampFormatter(ScriptingContainer jruby, String format, DateTimeZone timeZone)
|
|
37
|
+
{
|
|
38
|
+
this.timeZone = timeZone;
|
|
39
|
+
this.dateFormat = new RubyDateFormat(format, Locale.ENGLISH, true);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public void format(Timestamp value, LineEncoder encoder)
|
|
43
|
+
{
|
|
44
|
+
// TODO optimize by directly appending to internal buffer
|
|
45
|
+
encoder.addText(format(value));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public String format(Timestamp value)
|
|
49
|
+
{
|
|
50
|
+
// TODO optimize by using reused StringBuilder
|
|
51
|
+
dateFormat.setDateTime(new DateTime(value.toEpochMilli(), timeZone));
|
|
52
|
+
dateFormat.setNSec(value.getNano());
|
|
53
|
+
return dateFormat.format(null);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
package org.embulk.spi.time;
|
|
2
|
+
|
|
3
|
+
import org.joda.time.DateTimeZone;
|
|
4
|
+
import org.jruby.embed.ScriptingContainer;
|
|
5
|
+
import com.fasterxml.jackson.annotation.JacksonInject;
|
|
6
|
+
import org.embulk.config.Task;
|
|
7
|
+
import org.embulk.config.Config;
|
|
8
|
+
import org.embulk.config.ConfigDefault;
|
|
9
|
+
import org.embulk.config.ConfigException;
|
|
10
|
+
import static org.embulk.spi.time.TimestampFormat.parseDateTimeZone;
|
|
11
|
+
|
|
12
|
+
public class TimestampParser
|
|
13
|
+
{
|
|
14
|
+
public interface ParserTask
|
|
15
|
+
extends Task
|
|
16
|
+
{
|
|
17
|
+
@Config("default_timezone")
|
|
18
|
+
@ConfigDefault("\"UTC\"")
|
|
19
|
+
public DateTimeZone getDefaultTimeZone();
|
|
20
|
+
|
|
21
|
+
@JacksonInject
|
|
22
|
+
public ScriptingContainer getJRuby();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private final JRubyTimeParserHelper helper;
|
|
26
|
+
private final DateTimeZone defaultTimeZone;
|
|
27
|
+
|
|
28
|
+
public TimestampParser(String format, ParserTask task)
|
|
29
|
+
{
|
|
30
|
+
this(task.getJRuby(), format, task.getDefaultTimeZone());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// TODO this is still private because this might need current time
|
|
34
|
+
private TimestampParser(ScriptingContainer jruby, String format, DateTimeZone defaultTimeZone)
|
|
35
|
+
{
|
|
36
|
+
JRubyTimeParserHelperFactory helperFactory = (JRubyTimeParserHelperFactory) jruby.runScriptlet("Embulk::Java::TimeParserHelper::Factory.new");
|
|
37
|
+
// TODO get default current time from ExecTask.getExecTimestamp
|
|
38
|
+
this.helper = (JRubyTimeParserHelper) helperFactory.newInstance(format, 1970, 1, 1, 0, 0, 0, 0); // TODO default time zone
|
|
39
|
+
this.defaultTimeZone = defaultTimeZone;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public Timestamp parse(String text) throws TimestampParseException
|
|
43
|
+
{
|
|
44
|
+
long localMillis = helper.strptime(text);
|
|
45
|
+
String zone = helper.getZone();
|
|
46
|
+
|
|
47
|
+
DateTimeZone timeZone = defaultTimeZone;
|
|
48
|
+
if (zone != null) {
|
|
49
|
+
// TODO cache parsed zone?
|
|
50
|
+
timeZone = parseDateTimeZone(zone);
|
|
51
|
+
if (timeZone == null) {
|
|
52
|
+
throw new TimestampParseException();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
long milli = timeZone.convertLocalToUTC(localMillis, false);
|
|
57
|
+
|
|
58
|
+
return Timestamp.ofEpochMilli(milli);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
package org.embulk.spi.time;
|
|
2
|
+
|
|
3
|
+
import java.io.IOException;
|
|
4
|
+
import com.fasterxml.jackson.core.JsonGenerator;
|
|
5
|
+
import com.fasterxml.jackson.databind.Module;
|
|
6
|
+
import com.fasterxml.jackson.databind.module.SimpleModule;
|
|
7
|
+
import com.fasterxml.jackson.databind.SerializerProvider;
|
|
8
|
+
import com.fasterxml.jackson.databind.DeserializationContext;
|
|
9
|
+
import com.fasterxml.jackson.databind.JsonSerializer;
|
|
10
|
+
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
11
|
+
import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer;
|
|
12
|
+
import com.fasterxml.jackson.module.guice.ObjectMapperModule;
|
|
13
|
+
|
|
14
|
+
public class TimestampSerDe
|
|
15
|
+
{
|
|
16
|
+
public static void configure(ObjectMapperModule mapper)
|
|
17
|
+
{
|
|
18
|
+
SimpleModule module = new SimpleModule();
|
|
19
|
+
module.addSerializer(Timestamp.class, new DateTimeZoneSerializer());
|
|
20
|
+
module.addDeserializer(Timestamp.class, new DateTimeZoneDeserializer());
|
|
21
|
+
mapper.registerModule(module);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public static class DateTimeZoneSerializer
|
|
25
|
+
extends JsonSerializer<Timestamp>
|
|
26
|
+
{
|
|
27
|
+
@Override
|
|
28
|
+
public void serialize(Timestamp value, JsonGenerator jgen, SerializerProvider provider)
|
|
29
|
+
throws IOException
|
|
30
|
+
{
|
|
31
|
+
jgen.writeString(value.toString());
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public static class DateTimeZoneDeserializer
|
|
36
|
+
extends FromStringDeserializer<Timestamp>
|
|
37
|
+
{
|
|
38
|
+
public DateTimeZoneDeserializer()
|
|
39
|
+
{
|
|
40
|
+
super(Timestamp.class);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@Override
|
|
44
|
+
protected Timestamp _deserialize(String value, DeserializationContext context)
|
|
45
|
+
throws JsonMappingException
|
|
46
|
+
{
|
|
47
|
+
return Timestamp.fromString(value);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
package org.embulk.spi.type;
|
|
2
|
+
|
|
3
|
+
public abstract class AbstractType
|
|
4
|
+
implements Type
|
|
5
|
+
{
|
|
6
|
+
private final String name;
|
|
7
|
+
private final Class<?> javaType;
|
|
8
|
+
private byte fixedStorageSize;
|
|
9
|
+
|
|
10
|
+
protected AbstractType(String name, Class<?> javaType, int fixedStorageSize)
|
|
11
|
+
{
|
|
12
|
+
this.name = name;
|
|
13
|
+
this.javaType = javaType;
|
|
14
|
+
this.fixedStorageSize = (byte) fixedStorageSize;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@Override
|
|
18
|
+
public String getName()
|
|
19
|
+
{
|
|
20
|
+
return name;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Override
|
|
24
|
+
public Class<?> getJavaType()
|
|
25
|
+
{
|
|
26
|
+
return javaType;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Override
|
|
30
|
+
public byte getFixedStorageSize()
|
|
31
|
+
{
|
|
32
|
+
return fixedStorageSize;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@Override
|
|
36
|
+
public boolean equals(Object o)
|
|
37
|
+
{
|
|
38
|
+
if (o == null) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return o.getClass().isAssignableFrom(getClass());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Override
|
|
45
|
+
public int hashCode()
|
|
46
|
+
{
|
|
47
|
+
return getClass().hashCode();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@Override
|
|
51
|
+
public String toString()
|
|
52
|
+
{
|
|
53
|
+
return name;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package org.embulk.spi.type;
|
|
2
|
+
|
|
3
|
+
import org.embulk.spi.time.Timestamp;
|
|
4
|
+
|
|
5
|
+
public class TimestampType
|
|
6
|
+
extends AbstractType
|
|
7
|
+
{
|
|
8
|
+
static final TimestampType TIMESTAMP = new TimestampType();
|
|
9
|
+
|
|
10
|
+
private static final String DEFAULT_FORMAT = "%Y-%m-%d %H-%M-%S,%N %z";
|
|
11
|
+
|
|
12
|
+
private final String format;
|
|
13
|
+
|
|
14
|
+
private TimestampType()
|
|
15
|
+
{
|
|
16
|
+
this(null);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private TimestampType(String format)
|
|
20
|
+
{
|
|
21
|
+
super("timestamp", Timestamp.class, 12); // long msec + int nsec
|
|
22
|
+
this.format = format;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public TimestampType withFormat(String format)
|
|
26
|
+
{
|
|
27
|
+
// TODO is this correct design...?
|
|
28
|
+
return new TimestampType(format);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public String getFormat()
|
|
32
|
+
{
|
|
33
|
+
if (format == null) {
|
|
34
|
+
return DEFAULT_FORMAT;
|
|
35
|
+
} else {
|
|
36
|
+
return format;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package org.embulk.spi.type;
|
|
2
|
+
|
|
3
|
+
import com.fasterxml.jackson.annotation.JsonValue;
|
|
4
|
+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
|
5
|
+
|
|
6
|
+
@JsonDeserialize(using=TypeDeserializer.class)
|
|
7
|
+
public interface Type
|
|
8
|
+
{
|
|
9
|
+
@JsonValue
|
|
10
|
+
public String getName();
|
|
11
|
+
|
|
12
|
+
public Class<?> getJavaType();
|
|
13
|
+
|
|
14
|
+
public byte getFixedStorageSize();
|
|
15
|
+
}
|