DynamoDB Enhanced - DurationAttributeConverter incorrectly converts negative durations with nanosecond offsets
- Dominant language
- Java
- Stars
- 2.6k
- Forks
- 1k
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 51
Description
### Describe the bug
When converting a negative `Duration` with a non-zero nanosecond offset, DynamoDB enhanced client's `DurationAttributeConverter.transformFrom` will return a value that does not match the input. Passing that returned value back into `DurationAttributeConverter.transformTo` will not return a `Duration` equal to the original value.
### Regression Issue
- [ ] Select this option if this issue appears to be a regression.
### Expected Behavior
I expect that I will receive an equivalent value after converting a negative `Duration` with a non-zero nanosecond offset to and from an `AttributeValue` with `DurationAttributeConverter`.
For example, if I create a `DurationAttributeConverter` named `converter` and call `converter.transformFrom(Duration.ofMillis(-1))`, I'd expect to receive `AttributeValue.fromN("-0.001000000")`. Subsequently calling `converter.transformTo` on that result should return `Duration.ofMillis(-1)`.
### Current Behavior
Rather than receiving an equivalent value, I received a different value `Duration.parse("PT-1.999S")` from the `transformTo` call and a value of `AttributeValue.fromN("-1.999000000")` from the `transformFrom` call.
### Reproduction Steps
```java
DurationAttributeConverter converter = DurationAttributeConverter.create();
Duration original = Duration.ofMillis(-1);
// This assertion will fail
assert original.equals(converter.transformTo(converter.transformFrom(original)));
```
### Possible Solution
The most likely reason for this bug is the internal representation used by Java for negative durations. From the `java.time.Duration.getSeconds` Javadoc:
> A negative duration is expressed by the negative sign of the seconds part. A duration of -1 nanosecond is stored as -1 seconds plus 999,999,999 nanoseconds.
### Additional Information/Context
_No response_
### AWS Java SDK version used
2.41.32
### JDK version used
openjdk 25.0.3 2026-04-21 LTS OpenJDK Runtime Environment Corretto-25.0.3.9.1 (build 25.0.3+9-LTS) OpenJDK 64-Bit Server VM Corretto-25.0.3.9.1 (build 25.0.3+9-LTS, mixed mode, sharing)
### Operating System and version
Rocky Linux release 8.10 (Green Obsidian), but will occur on any OS
Contributor guide
Research direction
Start at DurationAttributeConverter and inspect transformFrom and transformTo, using the Duration.ofMillis(-1) reproduction from the issue. Add a regression test covering negative durations with non-zero nanosecond offsets, then run the converter's relevant tests and confirm the round trip returns the original Duration and expected AttributeValue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100