Skip to content
This repository was archived by the owner on Dec 16, 2021. It is now read-only.

Commit fcf3e36

Browse files
authored
Replace SimpleDateFormat with DateTimeFormatter (#21)
* Change java target version from 1.7 to 1.8 * Refactoring parseDate * Modify parsers * Remove openjdk7 * Modify Makefile, README and pom * Add ./dev/get-app-version.sh * Modify Makefile
1 parent c0eda6f commit fcf3e36

File tree

7 files changed

+95
-80
lines changed

7 files changed

+95
-80
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ sudo: false # faster builds
44
jdk:
55
- oraclejdk8
66
- oraclejdk9
7-
- openjdk7
87
- openjdk8
98

109
script:

Makefile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
#
44

55
DOCKER_TAG := yuiskw/bigquery-to-datastore:latest
6-
DOCKER_TAG_VERSION := yuiskw/bigquery-to-datastore:beam-2.1
6+
DOCKER_TAG_VERSION := yuiskw/bigquery-to-datastore:$(shell bash ./dev/get-app-version.sh)-beam-2.1
77

8-
.PHONY: test checkstyle clean
8+
.PHONY: test checkstyle clean \
9+
build-docker test-docker push-docker push-docker-latest push-docker-version
910

1011
all: checkstyle test package
1112

@@ -23,8 +24,8 @@ clean:
2324
mvn clean
2425

2526
build-docker: package
26-
docker build -t $(DOCKER_TAG) .
27-
docker build -t $(DOCKER_TAG_VERSION) .
27+
docker build --rm -t $(DOCKER_TAG) .
28+
docker build --rm -t $(DOCKER_TAG_VERSION) .
2829

2930
test-docker: build-docker
3031
docker run --rm --entrypoint "bash" $(DOCKER_TAG) ./dev/test.sh

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Apache Beam's `DatastoreIO` doesn't allow us to write same key at once.
1313
## Requirements
1414

1515
- Maven
16-
- Java 1.7+
16+
- Java 1.8+
1717
- Google Cloud Platform account
1818

1919
## Usage
@@ -46,7 +46,7 @@ Apache Beam's `DatastoreIO` doesn't allow us to write same key at once.
4646
mvn clean package
4747
4848
# Run bigquery-to-datastore via the compiled JAR file
49-
java -cp $(pwd)/target/bigquery-to-datastore-bundled-0.3.jar \
49+
java -cp $(pwd)/target/bigquery-to-datastore-bundled-0.5.0.jar \
5050
com.github.yuiskw.beam.BigQuery2Datastore \
5151
--project=your-gcp-project \
5252
--runner=DataflowRunner \
@@ -71,7 +71,7 @@ mvn clean package
7171
make package
7272
7373
# run
74-
java -cp $(pwd)/target/bigquery-to-datastore-bundled-0.3.jar --help
74+
java -cp $(pwd)/target/bigquery-to-datastore-bundled-0.5.0.jar --help
7575
# or
7676
./bin/bigquery-to-datastore --help
7777
```
@@ -80,7 +80,7 @@ java -cp $(pwd)/target/bigquery-to-datastore-bundled-0.3.jar --help
8080
We also offers docker images for this project in [yuiskw/bigquery\-to\-datastore \- Docker Hub](https://hub.docker.com/r/yuiskw/bigquery-to-datastore/).
8181
We have several docker images based on Apache Beam versions.
8282
```
83-
docker run yuiskw/bigquery-to-datastore:latest --help
83+
docker run yuiskw/bigquery-to-datastore:0.5.0-beam-2.1 --help
8484
```
8585

8686
### How to install it with homebrew
@@ -90,7 +90,7 @@ You can install it with homebrew from [yu-iskw/homebrew-bigquery-to-datastore](h
9090
brew install yu-iskw/bigquery-to-datastore/bigquery-to-datastore
9191
9292
# show help
93-
bigquery-to-datastore --help
93+
./bin/bigquery-to-datastore --help
9494
```
9595

9696
### Type conversions between BigQuery and Google Datastore

dev/get-app-version.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#
2+
# Copyright (c) 2017 Yu Ishikawa.
3+
#
4+
5+
#
6+
# This script is used for extracting the application version from pom.xml.
7+
#
8+
PROJECT_DIR=$(dirname $(dirname $(readlink -f $0)))
9+
XML_TAG=$(grep -e '<version>[0-9\.]*</version>' "${PROJECT_DIR}/pom.xml")
10+
VERSION=$(echo "$XML_TAG" | sed -e 's/<version>//' -e 's/<\/version>//' | tr -d '[:space:]')
11+
echo "$VERSION"

pom.xml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
<groupId>com.github.yuiskw</groupId>
2424
<artifactId>bigquery-to-datastore</artifactId>
25-
<version>0.4.1</version>
25+
<version>0.5.0</version>
2626

2727
<packaging>jar</packaging>
2828

@@ -67,8 +67,8 @@
6767
<artifactId>maven-compiler-plugin</artifactId>
6868
<version>${maven-compiler-plugin.version}</version>
6969
<configuration>
70-
<source>1.7</source>
71-
<target>1.7</target>
70+
<source>1.8</source>
71+
<target>1.8</target>
7272
</configuration>
7373
</plugin>
7474

@@ -173,7 +173,6 @@
173173
<groupId>org.apache.beam</groupId>
174174
<artifactId>beam-runners-google-cloud-dataflow-java</artifactId>
175175
<version>${beam.version}</version>
176-
<scope>runtime</scope>
177176
</dependency>
178177
</dependencies>
179178
</profile>

src/main/java/com/github/yuiskw/beam/TableRow2EntityFn.java

Lines changed: 45 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
*/
44
package com.github.yuiskw.beam;
55

6-
import java.text.DateFormat;
76
import java.text.ParseException;
8-
import java.text.SimpleDateFormat;
7+
import java.time.Instant;
8+
import java.time.ZoneId;
9+
import java.time.format.DateTimeFormatter;
10+
import java.time.format.DateTimeParseException;
11+
import java.time.format.ResolverStyle;
912
import java.util.*;
1013

1114
import com.google.api.services.bigquery.model.TableRow;
@@ -61,6 +64,14 @@ public static Timestamp toTimestamp(Date date) {
6164
return timestamp;
6265
}
6366

67+
public static Timestamp toTimestamp(Instant instant) {
68+
long second = instant.getEpochSecond();
69+
Timestamp timestamp = Timestamp.newBuilder()
70+
.setSeconds(second)
71+
.build();
72+
return timestamp;
73+
}
74+
6475
/**
6576
* Convert TableRow to Entity
6677
*/
@@ -120,8 +131,8 @@ else if (value instanceof org.joda.time.LocalDateTime) {
120131
.setExcludeFromIndexes(isExcluded).build();
121132
}
122133
else if (value instanceof String && parseTimestamp((String) value) != null) {
123-
Date date = parseTimestamp((String) value);
124-
Timestamp timestamp = toTimestamp(date);
134+
Instant instant = parseTimestamp((String) value);
135+
Timestamp timestamp = toTimestamp(instant);
125136
v = Value.newBuilder().setTimestampValue(timestamp)
126137
.setExcludeFromIndexes(isExcluded).build();
127138
}
@@ -131,18 +142,11 @@ else if (value instanceof org.joda.time.LocalDate) {
131142
v = Value.newBuilder().setTimestampValue(timestamp)
132143
.setExcludeFromIndexes(isExcluded).build();
133144
} else if (value instanceof String && parseDate((String) value) != null) {
134-
Date date = parseDate((String) value);
135-
Timestamp timestamp = toTimestamp(date);
145+
Instant instant = parseDate((String) value);
146+
Timestamp timestamp = toTimestamp(instant);
136147
v = Value.newBuilder().setTimestampValue(timestamp)
137148
.setExcludeFromIndexes(isExcluded).build();
138149
}
139-
// TIME
140-
// NOTE: Datastore doesn't have any data type to time.
141-
else if (value instanceof org.joda.time.LocalTime) {
142-
;
143-
} else if (value instanceof String && parseTime((String) value) != null) {
144-
;
145-
}
146150
// STRING
147151
else if (value instanceof String) {
148152
v = Value.newBuilder().setStringValue((String) value)
@@ -254,63 +258,51 @@ public static Integer parseInteger(String value) {
254258
*
255259
* Note: SimpledateFormat("yyyy-MM-dd") can't help parseing "yyyy-MM-dd HH:mm:ss" as well.
256260
*/
257-
public static Date parseDate(String value) {
258-
Date date = null;
261+
public static Instant parseDate(String value) {
262+
Instant instant = null;
259263
try {
260-
DateFormat sourceFormat = new SimpleDateFormat("yyyy-MM-dd");
261-
date = sourceFormat.parse(value);
262-
} catch (ParseException e) {
264+
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-d")
265+
.withResolverStyle(ResolverStyle.SMART);
266+
java.time.LocalDate localDate = java.time.LocalDate.parse(value, formatter);
267+
instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
268+
} catch (DateTimeParseException e) {
263269
// Do nothing.
264270
;
265271
}
266-
return date;
267-
}
268-
269-
/**
270-
* Parse string on time format
271-
*/
272-
public static Date parseTime(String value) {
273-
Date date = null;
274-
List<String> patterns = Arrays.asList(
275-
"HH:mm:ss.SSS z",
276-
"HH:mm:ss.SSS",
277-
"HH:mm:ss"
278-
);
279-
for (String pattern : patterns) {
280-
try {
281-
DateFormat sourceFormat = new SimpleDateFormat(pattern);
282-
date = sourceFormat.parse(value);
283-
return date;
284-
} catch (ParseException e) {
285-
// Do nothing.
286-
;
287-
}
288-
}
289-
return date;
272+
return instant;
290273
}
291274

292275
/**
293276
* Parse string on timestamp format
294277
*/
295-
public static Date parseTimestamp(String value) {
296-
Date date = null;
278+
public static Instant parseTimestamp(String value) {
279+
Instant instant = null;
297280
List<String> patterns = Arrays.asList(
298-
"yyyy-MM-dd HH:mm:ss.SSS z",
299-
"yyyy-MM-dd HH:mm:ss.SSS",
300-
"yyyy-MM-dd HH:mm:ss",
301-
"yyyy-MM-dd'T'HH:mm:ss"
281+
"yyyy-M-d H:m:s.SSS z",
282+
"yyyy-M-d H:m:s.SS z",
283+
"yyyy-M-d H:m:s.S z",
284+
"yyyy-M-d H:m:s.SSS",
285+
"yyyy-M-d H:m:s.SS",
286+
"yyyy-M-d H:m:s.S",
287+
"yyyy-M-d H:m:s",
288+
"yyyy-M-d'T'H:m:s.SSS",
289+
"yyyy-M-d'T'H:m:s.SS",
290+
"yyyy-M-d'T'H:m:s.S",
291+
"yyyy-M-d'T'H:m:s"
302292
);
303293
for (String pattern : patterns) {
304294
try {
305-
DateFormat sourceFormat = new SimpleDateFormat(pattern);
306-
date = sourceFormat.parse(value);
307-
return date;
308-
} catch (ParseException e) {
295+
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern)
296+
.withResolverStyle(ResolverStyle.SMART);
297+
java.time.LocalDateTime localDateTime = java.time.LocalDateTime.parse(value, formatter);
298+
instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
299+
return instant;
300+
} catch (DateTimeParseException e) {
309301
// Do nothing.
310302
;
311303
}
312304
}
313-
return date;
305+
return instant;
314306
}
315307

316308
/**

src/test/java/com/github/yuiskw/beam/TableRow2EntityFnTest.java

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.google.datastore.v1.Entity;
1313
import com.google.datastore.v1.Key;
1414
import com.google.datastore.v1.Value;
15+
import com.google.protobuf.Timestamp;
1516
import org.joda.time.DateTime;
1617
import org.joda.time.Instant;
1718

@@ -94,25 +95,30 @@ public void testConvert2() {
9495
public void testIsDate() {
9596
assertNotNull(TableRow2EntityFn.parseDate("2017-01-01"));
9697
assertNotNull(TableRow2EntityFn.parseDate("2017-1-1"));
98+
assertNotNull(TableRow2EntityFn.parseDate("2017-01-1"));
99+
assertNotNull(TableRow2EntityFn.parseDate("2017-1-01"));
100+
assertNotNull(TableRow2EntityFn.parseDate("2017-02-30"));
97101
assertNull(TableRow2EntityFn.parseDate("hoge"));
98102
}
99103

100-
@Test
101-
public void testIsTime() {
102-
assertNotNull(TableRow2EntityFn.parseTime("04:14:37.844024"));
103-
assertNotNull(TableRow2EntityFn.parseTime("4:4:7.4"));
104-
assertNotNull(TableRow2EntityFn.parseTime("04:14:37"));
105-
assertNull(TableRow2EntityFn.parseTime("hoge"));
106-
}
107-
108104
@Test
109105
public void testIsTimestamp() {
110-
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-09-16 04:14:37.844024 UTC"));
111-
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-09-16 04:14:37.844024 PST"));
112-
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-09-16 04:14:37.844024 JST"));
113-
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-9-16 4:14:37.844024 UTC"));
114-
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-09-16T04:14:37.844024"));
106+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-09-16 04:14:37.844 UTC"));
107+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-9-1 4:1:1.1 UTC"));
108+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-9-1 4:1:1.12 UTC"));
109+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-9-1 4:1:1.001 UTC"));
110+
111+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-09-16 04:14:37.844 PST"));
112+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-09-16 04:14:37.844 JST"));
113+
114+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-09-16T04:14:37.844"));
115+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-9-01T4:1:1.1"));
116+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-9-01T4:1:1.12"));
117+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-9-01T4:1:1.001"));
115118
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-09-16 04:14:37"));
119+
assertNotNull(TableRow2EntityFn.parseTimestamp("2017-9-01 4:02:03"));
120+
121+
assertNull(TableRow2EntityFn.parseDate("98-9-12.com"));
116122
assertNull(TableRow2EntityFn.parseTimestamp("hoge"));
117123
}
118124

@@ -125,4 +131,11 @@ public void testIsExlucedFromIndex() {
125131

126132
assertTrue(TableRow2EntityFn.isExcludedFromIndex(null, indexedColumns));
127133
}
134+
135+
@Test
136+
public void testToTimestamp() {
137+
java.time.Instant instant = java.time.Instant.now();
138+
Timestamp timestamp = TableRow2EntityFn.toTimestamp(instant);
139+
assertEquals(instant.getEpochSecond(), timestamp.getSeconds());
140+
}
128141
}

0 commit comments

Comments
 (0)