Skip to content

Commit 053d896

Browse files
author
Ronald Holshausen
committedApr 18, 2020
fix: datetime expressions where the time modifier rolls the date
1 parent e30821d commit 053d896

File tree

7 files changed

+24
-29
lines changed

7 files changed

+24
-29
lines changed
 

‎core/model/src/main/kotlin/au/com/dius/pact/core/model/generators/DateTimeExpression.kt

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@ package au.com.dius.pact.core.model.generators
33
import au.com.dius.pact.com.github.michaelbull.result.Err
44
import au.com.dius.pact.com.github.michaelbull.result.Ok
55
import au.com.dius.pact.com.github.michaelbull.result.Result
6-
import au.com.dius.pact.com.github.michaelbull.result.get
7-
import au.com.dius.pact.com.github.michaelbull.result.map
86
import au.com.dius.pact.com.github.michaelbull.result.mapError
97
import mu.KLogging
108
import java.lang.Integer.parseInt
119
import java.time.OffsetDateTime
12-
import java.time.temporal.ChronoUnit
1310

1411
object DateTimeExpression : KLogging() {
1512
fun executeExpression(base: OffsetDateTime, expression: String?): Result<OffsetDateTime, String> {
1613
return if (!expression.isNullOrEmpty()) {
1714
val split = expression.split("@", limit = 2)
1815
if (split.size > 1) {
1916
val datePart = DateExpression.executeDateExpression(base, split[0])
20-
val timePart = TimeExpression.executeTimeExpression(base.toOffsetTime(), split[1])
17+
val timePart = if (datePart is Ok<OffsetDateTime>)
18+
TimeExpression.executeTimeExpression(datePart.value, split[1])
19+
else
20+
TimeExpression.executeTimeExpression(base, split[1])
2121
when {
2222
datePart is Err<String> && timePart is Err<String> -> datePart.mapError { "$it, " +
2323
Regex("1:(\\d+)").replace(timePart.error) { mr ->
@@ -32,7 +32,7 @@ object DateTimeExpression : KLogging() {
3232
"1:${pos + split[0].length + 1}"
3333
}
3434
}
35-
else -> datePart.map { it.truncatedTo(ChronoUnit.DAYS).with(timePart.get()!!.toLocalTime()) }
35+
else -> timePart
3636
}
3737
} else {
3838
DateExpression.executeDateExpression(base, split[0])

‎core/model/src/main/kotlin/au/com/dius/pact/core/model/generators/Generator.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import org.apache.commons.lang3.RandomStringUtils
1414
import org.apache.commons.lang3.RandomUtils
1515
import java.math.BigDecimal
1616
import java.time.OffsetDateTime
17-
import java.time.OffsetTime
1817
import java.time.format.DateTimeFormatter
1918
import java.util.UUID
2019
import java.util.concurrent.ThreadLocalRandom
@@ -276,7 +275,7 @@ data class TimeGenerator @JvmOverloads constructor(val format: String? = null, v
276275
}
277276

278277
override fun generate(context: Map<String, Any?>): Any {
279-
val base = if (context.containsKey("baseTime")) context["baseTime"] as OffsetTime else OffsetTime.now()
278+
val base = if (context.containsKey("baseTime")) context["baseTime"] as OffsetDateTime else OffsetDateTime.now()
280279
val time = TimeExpression.executeTimeExpression(base, expression).getOr { base }
281280
return if (!format.isNullOrEmpty()) {
282281
time.format(DateTimeFormatter.ofPattern(format))

‎core/model/src/main/kotlin/au/com/dius/pact/core/model/generators/TimeExpression.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,20 @@ import mu.KLogging
1313
import org.antlr.v4.runtime.CharStreams
1414
import org.antlr.v4.runtime.CommonTokenStream
1515
import java.time.LocalTime
16-
import java.time.OffsetTime
16+
import java.time.OffsetDateTime
1717
import java.time.ZoneOffset
1818
import java.time.temporal.ChronoUnit
1919

2020
data class ParsedTimeExpression(val base: TimeBase, val adjustments: MutableList<Adjustment<TimeOffsetType>>)
2121

2222
object TimeExpression : KLogging() {
23-
fun executeTimeExpression(base: OffsetTime, expression: String?): Result<OffsetTime, String> {
23+
fun executeTimeExpression(base: OffsetDateTime, expression: String?): Result<OffsetDateTime, String> {
2424
return if (!expression.isNullOrEmpty()) {
2525
return when (val result = parseTimeExpression(expression)) {
2626
is Err -> result
2727
is Ok -> {
28-
val midnight = OffsetTime.of(LocalTime.MIDNIGHT, ZoneOffset.from(base))
29-
val noon = OffsetTime.of(LocalTime.NOON, ZoneOffset.from(base))
28+
val midnight = OffsetDateTime.of(base.toLocalDate(), LocalTime.MIDNIGHT, ZoneOffset.from(base))
29+
val noon = OffsetDateTime.of(base.toLocalDate(), LocalTime.NOON, ZoneOffset.from(base))
3030
var time = when (val valBase = result.value.base) {
3131
TimeBase.Now -> base
3232
TimeBase.Midnight -> midnight

‎core/model/src/test/groovy/au/com/dius/pact/core/model/generators/DateTimeExpressionSpec.groovy

+10-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class DateTimeExpressionSpec extends Specification {
8383
expression | expected
8484
'today @ 1 o\'clock' | '2000-01-01T13:00Z'
8585
'yesterday @ midnight' | '1999-12-31T00:00Z'
86-
'yesterday @ midnight - 1 hour' | '1999-12-31T23:00Z'
86+
'yesterday @ midnight - 1 hour' | '1999-12-30T23:00Z'
8787
'tomorrow @ now' | '2000-01-02T10:00Z'
8888
'+ 1 day @ noon' | '2000-01-02T12:00Z'
8989
'+ 1 week @ +1 hour' | '2000-01-08T11:00Z'
@@ -111,4 +111,13 @@ class DateTimeExpressionSpec extends Specification {
111111
'now @ now +' | 'Error parsing expression: line 1:11 mismatched input \'<EOF>\' expecting INT'
112112
'now @ noo' | /^Error parsing expression.*/
113113
}
114+
115+
def 'Time expressions that cause the date to roll'() {
116+
expect:
117+
DateTimeExpression.INSTANCE.executeExpression(base, '+ 1 day @ + 1 hour').value.toString() == datetime
118+
119+
where:
120+
base = OffsetDateTime.parse('2020-04-14T23:20:00.311Z')
121+
datetime = base.plusDays(1).plusHours(1).format('yyyy-MM-dd\'T\'HH:mm:ss.SSSX')
122+
}
114123
}

‎core/model/src/test/groovy/au/com/dius/pact/core/model/generators/DateTimeGeneratorSpec.groovy

-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package au.com.dius.pact.core.model.generators
22

3-
import spock.lang.Ignore
43
import spock.lang.Specification
54

65
import java.time.OffsetDateTime
@@ -14,18 +13,6 @@ class DateTimeGeneratorSpec extends Specification {
1413
/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[-+]\d+/
1514
}
1615

17-
// This fails on CI before 11am AEST
18-
// FAILED
19-
// Condition not satisfied:
20-
// new DateTimeGenerator('yyyy-MM-dd\'T\'HH:mm:ssZ', '+ 1 day @ + 1 hour') .generate([baseDateTime: base]) == datetime
21-
// | | | | |
22-
// | 2020-04-15T00:20:00+0000| | 2020-04-16T00:20:00+0000
23-
// DateTimeGenerator(format=yyyy-MM-dd'T'HH:mm:ssZ, expression=+ 1 day @ + 1 hour) | false
24-
// | 1 difference (95% similarity)
25-
// | 2020-04-1(5)T00:20:00+0000
26-
// | 2020-04-1(6)T00:20:00+0000
27-
// 2020-04-14T23:20:00.311Z
28-
@Ignore
2916
def 'Uses any defined expression to generate the datetime value'() {
3017
expect:
3118
new DateTimeGenerator('yyyy-MM-dd\'T\'HH:mm:ssZ', '+ 1 day @ + 1 hour')

‎core/model/src/test/groovy/au/com/dius/pact/core/model/generators/TimeExpressionSpec.groovy

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import au.com.dius.pact.core.model.generators.TimeExpression
44
import spock.lang.Specification
55
import spock.lang.Unroll
66

7-
import java.time.OffsetTime
7+
import java.time.OffsetDateTime
88
import java.time.ZoneOffset
99
import java.time.format.DateTimeFormatter
1010

@@ -13,7 +13,7 @@ class TimeExpressionSpec extends Specification {
1313
private time
1414

1515
def setup() {
16-
time = OffsetTime.of(10, 0, 0, 0, ZoneOffset.UTC)
16+
time = OffsetDateTime.of(2000, 4, 3, 10, 0, 0, 0, ZoneOffset.UTC)
1717
}
1818

1919
@Unroll

‎core/model/src/test/groovy/au/com/dius/pact/core/model/generators/TimeGeneratorSpec.groovy

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package au.com.dius.pact.core.model.generators
22

33
import spock.lang.Specification
44

5-
import java.time.OffsetTime
5+
import java.time.OffsetDateTime
66

77
class TimeGeneratorSpec extends Specification {
88

@@ -16,7 +16,7 @@ class TimeGeneratorSpec extends Specification {
1616
new TimeGenerator('HH:mm:ss', '+ 1 hour').generate([baseTime: base]) == time
1717

1818
where:
19-
base = OffsetTime.now()
19+
base = OffsetDateTime.now()
2020
time = base.plusHours(1).format('HH:mm:ss')
2121
}
2222

0 commit comments

Comments
 (0)
Please sign in to comment.