Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xmas 2023 #19

Merged
merged 7 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ An extremely fast parser and formatter of ISO format date-times.

> Date and time formats cause a lot of confusion and interoperability problems on the Internet. This document addresses many of the problems encountered and makes recommendations to improve consistency and interoperability when representing and using date and time in Internet protocols.

This project's goal it to do one thing and to do it right; make it easy to
This project's goal is to do one thing and to do it right; make it easy to
handle [Date and Time on the Internet: Timestamps](https://www.ietf.org/rfc/rfc3339.txt) and
W3C [Date and Time Formats](https://www.w3.org/TR/NOTE-datetime) in Java.

Expand All @@ -21,9 +21,24 @@ W3C [Date and Time Formats](https://www.w3.org/TR/NOTE-datetime) in Java.

## Performance

Your mileage may vary, but tests indicate comfortably 10x faster than JDK classes.
<img src="doc/performance.png" alt="Performance plot">
Your mileage may vary. I've done my best to make sure these tests are as accurate as possible, but please do your own evaluation.
* The second resolution test-string is: `2017-12-21T12:20:45Z`
* The nanosecond-resolution test-string is: `2017-12-21T12:20:45.987654321Z`

### Parsing
<img src="doc/parse.png" alt="Performance of parsing">

### Formatting
<img src="doc/format.png" alt="Performance of formatting">

### Raw parsing
If you do not need to have the full verification of `java.time.OffsetDateTime`,
you can use the raw, parsed data through `com.ethlo.time.DateTime` that incurs less overhead.

Here it becomes even more visible how the parser scales with the length of the string that is parsed.
<img src="doc/parse_raw.png" alt="Performance of raw parsing">

### Environment
Tests performed on a Lenovo P1 G6 laptop:
* Intel(R) Core(TM) i9-13900H
* Ubuntu 23.10
Expand All @@ -36,7 +51,7 @@ mvn jmh:benchmark

To plot the result and create the resulting image, you can run `plot.py`, for example:
```
python3 plot.py -i target/itu_performance.json --size=11,5
python3 plot.py -i target/itu_performance.json
```

## Example usage
Expand All @@ -47,7 +62,7 @@ Add dependency
<dependency>
<groupId>com.ethlo.time</groupId>
<artifactId>itu</artifactId>
<version>1.7.3</version>
<version>1.7.4</version>
</dependency>
```

Expand Down Expand Up @@ -181,7 +196,7 @@ serves as a sane subset of ISO-8601, just like RFC-3339.
Typical formats include:

* `2017-12-27T23:45Z` - Minute resolution, UTC/Zulu time
* `2017-12-27` - Date only, no timezone (like someones birthday)
* `2017-12-27` - Date only, no timezone (like someone's birthday)
* `2017-12` - Year and month only. Like an expiry date.

## Limitations
Expand All @@ -204,6 +219,11 @@ instead of `60`.

## Changelog

### Version 1.7.4

2023-12-26
* Parser performance improvements.

### Version 1.7.0

2022-09-03
Expand Down
Binary file added doc/format.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/parse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/parse_raw.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/performance.png
Binary file not shown.
4 changes: 2 additions & 2 deletions plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def __init__(self):
self.parser = argparse.ArgumentParser(description='ReportGenerator')
self.parser.add_argument('-i', default='target/itu_performance.json', help='The JMH result (JSON) file')
self.parser.add_argument('-o', default='output.png', help='Output file path for bar chart image')
self.parser.add_argument('--size', default='10,16', help='Plot size')
self.parser.add_argument('--size', default='18,8', help='Plot size')
self.parser.add_argument('--theme', default='default', help='Output theme for bar chart image')
self.parser.add_argument('--include', default='parse,parseRaw,format',
help='Prefix for test methods to include')
Expand All @@ -38,7 +38,7 @@ def render(self, dtf, target):
plot = dtf.plot(x=0,
kind='barh',
stacked=False,
title='Nanoseconds per operation (lower is better)',
title='Operations per millisecond (higher is better)',
figsize=self.fig_size)

for container in plot.containers:
Expand Down
24 changes: 12 additions & 12 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ limitations under the License.
<groupId>com.ethlo.time</groupId>
<packaging>bundle</packaging>
<artifactId>itu</artifactId>
<version>1.7.3</version>
<version>1.7.4-SNAPSHOT</version>
<name>Internet Time Utility</name>
<description>Extremely fast date/time parser and formatter - RFC 3339 (ISO 8601 profile) and W3C format
<description>Very fast date-time parser and formatter - RFC 3339 (ISO 8601 profile) and W3C format
</description>
<licenses>
<license>
Expand Down Expand Up @@ -65,25 +65,25 @@ limitations under the License.
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
<version>3.14.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
<version>1.43.1</version>
<version>1.43.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.35</version>
<version>1.37</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.35</version>
<version>1.37</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -97,7 +97,7 @@ limitations under the License.
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<version>3.12.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
Expand All @@ -111,14 +111,14 @@ limitations under the License.
<configuration>
<source>1.8</source>
<target>1.8</target>
<benchmarkMode>SampleTime</benchmarkMode>
<warmupIterations>1</warmupIterations>
<warmup>30</warmup>
<benchmarkMode>Throughput</benchmarkMode>
<warmupIterations>10</warmupIterations>
<warmup>2</warmup>
<fork>1</fork>
<resultFormat>JSON</resultFormat>
<resultsFile>target/itu_performance.json</resultsFile>
<iterations>3</iterations>
<timeOnIteration>10</timeOnIteration>
<iterations>10</iterations>
<timeOnIteration>2</timeOnIteration>
</configuration>
</plugin>
<plugin>
Expand Down
4 changes: 4 additions & 0 deletions render.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
python3 plot.py --include=parse -i target/itu_performance.json --theme theme.mplstyle --size=12,4 -o doc/parse.png
python3 plot.py --include=format -i target/itu_performance.json --theme theme.mplstyle --size=12,4 -o doc/format.png
python3 plot.py --include=raw -i target/itu_performance.json --theme theme.mplstyle --size=12,4 -o doc/parse_raw.png
5 changes: 5 additions & 0 deletions src/main/java/com/ethlo/time/DateTime.java
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,11 @@ public LocalDateTime toLocalDatetime()
public OffsetDateTime toOffsetDatetime()
{
assertMinGranularity(Field.MINUTE);
return toOffsetDatetimeNoGranularityCheck();
}

public OffsetDateTime toOffsetDatetimeNoGranularityCheck()
{
if (offset != null)
{
return OffsetDateTime.of(year, month, day, hour, minute, second, nano, offset.toZoneOffset());
Expand Down
Loading