gnodet-bot commented on PR #599:
URL: https://github.com/apache/maven-jar-plugin/pull/599#issuecomment-5806162612

   @desruisseaux — Good catch on the "why 2 seconds" question. The short answer 
is: the 2-second floor is a **JDK `jar` tool decision**, not a ZIP format 
requirement, but it exists for a real reason.
   
   The ZIP/MS-DOS time format (16-bit) encodes seconds as `seconds ÷ 2`, giving 
2-second granularity with a minimum representable value of 
`1980-01-01T00:00:00Z` (all bits zero in the time word). That instant is not 
forbidden by the ZIP specification — it is encodable.
   
   The problem is that `1980-01-01T00:00:00Z` is used as a **sentinel value** 
in the ZIP extended timestamp (UT/Unix extra field): the Java 
`ZipEntry.javaToDosTime()` method returns the bit pattern `0x210000` 
(`DOSTIME_BEFORE_1980`) for any date before 1980, and the extended field uses 
that exact sentinel to signal "this entry has no valid DOS timestamp". When you 
pass `1980-01-01T00:00:00Z` verbatim, the reader sees the sentinel and 
interprets it as pre-1980, then falls back to the UTC extra field timestamp — 
which gets misread as a local time, producing `1980-01-01T08:00:00Z` instead of 
UTC midnight (this is the bug reported during the original OpenJDK `--date` 
implementation review).
   
   To avoid anyone accidentally triggering this sentinel ambiguity, the JDK 
`jar` tool was deliberately set to reject `T00:00:00Z` and require `T00:00:02Z` 
as the minimum — one even-second step past the sentinel. This is a conservative 
margin by the `jar` tool implementers (see [openjdk-dev 
discussion](https://mail.openjdk.org/pipermail/compiler-dev/2021-December/018755.html)),
 not a ZIP format constraint.
   
   **Implication for the Javadoc on `EPOCH_MIN`:** The current wording — *"The 
ZIP format stores entry timestamps in MS-DOS time format, which has 2-second 
granularity and whose earliest representable value maps to 
1980-01-01T00:00:02Z"* — is slightly imprecise. The ZIP format's earliest 
representable value is actually `1980-01-01T00:00:00Z`; it is the **JDK `jar` 
tool** that enforces `T00:00:02Z` to avoid the sentinel. A more accurate 
phrasing would be:
   
   ```java
   /**
    * Minimum Unix time (seconds since epoch) accepted by the {@code jar} tool.
    * The ZIP format stores entry timestamps in MS-DOS time format, which has 
2-second
    * granularity and whose earliest representable value is 
1980-01-01T00:00:00Z.
    * However, the JDK {@code jar} tool rejects that instant because it is used 
as a
    * sentinel value in ZIP extended timestamp fields, and requires at least
    * 1980-01-01T00:00:02Z instead.
    * A JUnit test verifies that this constant equals
    * {@code Instant.parse("1980-01-01T00:00:02Z").getEpochSecond()}.
    */
   ```
   
   _This review was generated by an AI agent, Hermès on behalf of @gnodet._
   
   <!-- reviewer: gnodet-bot -->


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to