Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added TimestampFormatConfig, TimestampFormatter and TimestampParser
- Loading branch information
Showing
16 changed files
with
329 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
require 'quickload/error' | ||
require 'quickload/plugin' | ||
require 'quickload/java/time_helper' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
require 'java' | ||
|
||
module QuickLoad::Java | ||
require 'quickload/java/imports' | ||
|
||
class TimeParserHelper | ||
java_implements 'org.quickload.time.JRubyTimeParserHelper' | ||
|
||
class Factory | ||
java_implements 'org.quickload.time.JRubyTimeParserHelperFactory' | ||
|
||
# Override | ||
def newInstance(format_string, year, mon, day, hour, min, sec, usec) | ||
default_time = Time.utc(year, mon, day, hour, min, sec, usec) | ||
TimeParserHelper.new(format_string, default_time) | ||
end | ||
end | ||
|
||
def initialize(format_string, default_time) | ||
@format_string = format_string | ||
@default_time = default_time | ||
end | ||
|
||
# Override | ||
def strptime(text) | ||
hash = Date._strptime(text, @format_string) | ||
unless hash | ||
raise Java::TimestampParseException.new | ||
end | ||
|
||
if seconds = d[:seconds] | ||
return seconds * 1_000_000 | ||
|
||
else | ||
year = d[:year] | ||
mon = d[:mon] | ||
day = d[:mday] | ||
hour = d[:hour] | ||
min = d[:min] | ||
sec = d[:sec] | ||
sec_fraction = d[:sec_fraction] | ||
zone = d[:zone] | ||
usec = d[:sec_fraction] ? d[:sec_fraction] * 1000000 : nil | ||
|
||
now = @default_time | ||
begin | ||
break if year; year = now.year | ||
break if mon; mon = now.mon | ||
break if day; day = now.day | ||
break if hour; hour = now.hour | ||
break if min; min = now.min | ||
break if sec; sec = now.sec | ||
break if sec_fraction; usec = now.tv_usec | ||
end until true | ||
|
||
year ||= 1970 | ||
mon ||= 1 | ||
day ||= 1 | ||
hour ||= 0 | ||
min ||= 0 | ||
sec ||= 0 | ||
usec ||= 0 | ||
|
||
@zone = zone | ||
time = Time.utc(year, mon, day, hour, min, sec, usec).to_i | ||
return time.tv_sec * 1_000_000 + time.tv_usec | ||
end | ||
end | ||
|
||
# Override | ||
def getZone | ||
@zone | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
quickload-core/src/main/java/org/quickload/time/JRubyTimeParserHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package org.quickload.time; | ||
|
||
public interface JRubyTimeParserHelper | ||
{ | ||
public long strptime(String text) throws TimestampParseException; | ||
|
||
public String getZone(); | ||
} |
6 changes: 6 additions & 0 deletions
6
quickload-core/src/main/java/org/quickload/time/JRubyTimeParserHelperFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package org.quickload.time; | ||
|
||
public interface JRubyTimeParserHelperFactory | ||
{ | ||
public JRubyTimeParserHelper newInstance(String formatString, int year, int mon, int day, int hour, int min, int sec, int usec); | ||
} |
5 changes: 0 additions & 5 deletions
5
quickload-core/src/main/java/org/quickload/time/TimestampFormat.java
This file was deleted.
Oops, something went wrong.
99 changes: 99 additions & 0 deletions
99
quickload-core/src/main/java/org/quickload/time/TimestampFormatConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package org.quickload.time; | ||
|
||
import java.util.Set; | ||
import java.util.Date; | ||
import java.text.SimpleDateFormat; | ||
import java.text.ParsePosition; | ||
import com.google.common.collect.ImmutableSet; | ||
import com.fasterxml.jackson.annotation.JsonValue; | ||
import org.joda.time.DateTimeZone; | ||
import org.joda.time.format.DateTimeFormat; | ||
import org.jruby.embed.ScriptingContainer; | ||
|
||
public class TimestampFormatConfig | ||
{ | ||
private final ScriptingContainer jruby; | ||
private final String format; | ||
|
||
public TimestampFormatConfig(ScriptingContainer jruby, String format) | ||
{ | ||
this.jruby = jruby; | ||
this.format = format; | ||
} | ||
|
||
@JsonValue | ||
public String getFormat() | ||
{ | ||
return format; | ||
} | ||
|
||
public TimestampFormatter newFormatter(TimestampFormatterTask task) | ||
{ | ||
return new TimestampFormatter(jruby, format, task); | ||
} | ||
|
||
public TimestampParser newParser(TimestampParserTask task) | ||
{ | ||
return new TimestampParser(jruby, format, task); | ||
} | ||
|
||
private static Set<String> availableTimeZoneNames = ImmutableSet.copyOf(DateTimeZone.getAvailableIDs()); | ||
|
||
static DateTimeZone parseDateTimeZone(String s) | ||
{ | ||
if(s.startsWith("+") || s.startsWith("-")) { | ||
return DateTimeZone.forID("GMT"+s); | ||
|
||
} else { | ||
try { | ||
int rawOffset = (int) DateTimeFormat.forPattern("z").parseMillis(s); | ||
if(rawOffset == 0) { | ||
return DateTimeZone.UTC; | ||
} | ||
int offset = rawOffset / -1000; | ||
int h = offset / 3600; | ||
int m = offset % 3600; | ||
return DateTimeZone.forOffsetHoursMinutes(h, m); | ||
} catch (IllegalArgumentException ex) { | ||
// parseMillis failed | ||
} | ||
|
||
// TimeZone.getTimeZone returns GMT zone if given timezone id is not found | ||
// we want to only return timezone if exact match, otherwise exception | ||
if (availableTimeZoneNames.contains(s)) { | ||
//return TimeZone.getTimeZone(s); | ||
return DateTimeZone.forID(s); | ||
} | ||
return null; | ||
} | ||
} | ||
|
||
//// Java standard TimeZone | ||
//static TimeZone parseDateTimeZone(String s) | ||
//{ | ||
// if(s.startsWith("+") || s.startsWith("-")) { | ||
// return TimeZone.getTimeZone("GMT"+s); | ||
// | ||
// } else { | ||
// ParsePosition pp = new ParsePosition(0); | ||
// Date off = new SimpleDateFormat("z").parse(s, pp); | ||
// if(off != null && pp.getErrorIndex() == -1) { | ||
// int rawOffset = (int) off.getTime(); | ||
// if(rawOffset == 0) { | ||
// return TimeZone.UTC; | ||
// } | ||
// int offset = rawOffset / -1000; | ||
// int h = offset / 3600; | ||
// int m = offset % 3600; | ||
// return DateTimeZone.getTimeZone(String.format("GMT%+02d%02d", h, m)); | ||
// } | ||
// | ||
// // TimeZone.getTimeZone returns GMT zone if given timezone id is not found | ||
// // we want to only return timezone if exact match, otherwise exception | ||
// if (availableTimeZoneNames.contains(s)) { | ||
// return TimeZone.getTimeZone(s); | ||
// } | ||
// return null; | ||
// } | ||
//} | ||
} |
39 changes: 39 additions & 0 deletions
39
quickload-core/src/main/java/org/quickload/time/TimestampFormatConfigSerDe.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package org.quickload.time; | ||
|
||
import com.google.inject.Inject; | ||
import org.jruby.embed.ScriptingContainer; | ||
import com.fasterxml.jackson.databind.module.SimpleModule; | ||
import com.fasterxml.jackson.databind.DeserializationContext; | ||
import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer; | ||
import org.quickload.config.ModelManager; | ||
|
||
public class TimestampFormatConfigSerDe | ||
{ | ||
@Inject | ||
public TimestampFormatConfigSerDe(ModelManager modelManager, ScriptingContainer jruby) | ||
{ | ||
SimpleModule module = new SimpleModule(); | ||
|
||
module.addDeserializer(TimestampFormatConfig.class, new TimestampFormatConfigDeserializer(jruby)); | ||
|
||
modelManager.addObjectMapperModule(module); | ||
} | ||
|
||
public static class TimestampFormatConfigDeserializer | ||
extends FromStringDeserializer<TimestampFormatConfig> | ||
{ | ||
private final ScriptingContainer jruby; | ||
|
||
public TimestampFormatConfigDeserializer(ScriptingContainer jruby) | ||
{ | ||
super(TimestampFormatConfig.class); | ||
this.jruby = jruby; | ||
} | ||
|
||
@Override | ||
protected TimestampFormatConfig _deserialize(String value, DeserializationContext context) | ||
{ | ||
return new TimestampFormatConfig(jruby, value); | ||
} | ||
} | ||
} |
33 changes: 29 additions & 4 deletions
33
quickload-core/src/main/java/org/quickload/time/TimestampFormatter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,39 @@ | ||
package org.quickload.time; | ||
|
||
import java.util.Locale; | ||
import org.joda.time.DateTime; | ||
import org.joda.time.DateTimeZone; | ||
import org.jruby.embed.ScriptingContainer; | ||
import org.jruby.util.RubyDateFormat; | ||
import static org.quickload.time.TimestampFormatConfig.parseDateTimeZone; | ||
import org.quickload.spi.LineEncoder; | ||
import org.quickload.config.ConfigException; | ||
|
||
public class TimestampFormatter | ||
{ | ||
public TimestampFormatter(TimestampFormat format) | ||
private final RubyDateFormat dateFormat; | ||
private final DateTimeZone timeZone; | ||
|
||
public TimestampFormatter(ScriptingContainer jruby, String format, TimestampFormatterTask task) | ||
{ | ||
this.timeZone = parseDateTimeZone(task.getTimeZone()); | ||
if (timeZone == null) { | ||
throw new ConfigException("Unsupported timezone '"+task.getTimeZone()+"'"); | ||
} | ||
this.dateFormat = new RubyDateFormat(format, Locale.ENGLISH, true); | ||
} | ||
|
||
public void format(Timestamp value, LineEncoder encoder) | ||
{ | ||
// TODO optimize by directly appending to internal buffer | ||
encoder.addText(format(value)); | ||
} | ||
|
||
public String format() | ||
public String format(Timestamp value) | ||
{ | ||
// TODO | ||
return ""; | ||
// TODO optimize by using reused StringBuilder | ||
dateFormat.setDateTime(new DateTime(value.toEpochMilli(), timeZone)); | ||
dateFormat.setNSec(value.getNano()); | ||
return dateFormat.format(null); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
quickload-core/src/main/java/org/quickload/time/TimestampFormatterTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.quickload.time; | ||
|
||
import org.quickload.config.Config; | ||
import org.quickload.config.ConfigDefault; | ||
|
||
public interface TimestampFormatterTask | ||
{ | ||
@Config("timezone") | ||
@ConfigDefault("\"UTC\"") | ||
// TODO TimeZone SerDe | ||
public String getTimeZone(); | ||
} |
6 changes: 6 additions & 0 deletions
6
quickload-core/src/main/java/org/quickload/time/TimestampParseException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package org.quickload.time; | ||
|
||
public class TimestampParseException | ||
extends Exception | ||
{ | ||
} |
Oops, something went wrong.