Skip to content

Preserve sub-second precision when serializing timestamps - #3353

Merged
smilkuri merged 1 commit into
aws:masterfrom
jonathan343:preserve-subsecond-timestamps
Sep 17, 2026
Merged

smilkuri merged 1 commit into
aws:masterfrom
jonathan343:preserve-subsecond-timestamps

Conversation

@jonathan343

Copy link
Copy Markdown
Contributor

Overview

The PHP SDK serializes request timestamps by calling DateTimeInterface::getTimestamp() (or strtotime() for strings), which returns whole seconds and drops any sub-second precision the caller provided. This affects the unixTimestamp format used by json, rest-json, and smithy-rpc-v2-cbor bodies, and the iso8601 format used by query, rest-xml, and REST querystring/URI bindings. rfc822 (HTTP-date) only supports whole seconds and is unchanged.

This PR preserves the caller's sub-second precision for unixTimestamp and iso8601. Whole-second timestamps serialize exactly as before. It is the PHP counterpart to boto/botocore#3796 and fixes the PHP equivalent of boto/botocore#3255.

Testing

Added unit tests for TimestampShape::format() / formatAsString() and end-to-end serializer tests for json, query, rest-xml, and rest-json bindings. Protocol compliance tests pass. PHPStan reports no errors on the touched files.

Reproduced the scenario from boto/botocore#3255 with KinesisVideoArchivedMedia::listFragments, capturing the serialized body with a mock handler:

<?php
require 'vendor/autoload.php';

use Aws\KinesisVideoArchivedMedia\KinesisVideoArchivedMediaClient;
use Aws\Result;
use GuzzleHttp\Promise\Create;

$client = new KinesisVideoArchivedMediaClient([
    'region' => 'us-east-1',
    'version' => 'latest',
    'credentials' => ['key' => 'AKID', 'secret' => 'SECRET'],
    // Capture the serialized request instead of sending it.
    'handler' => function ($command, $request) {
        echo "POST {$request->getUri()->getPath()}\n";
        echo "body: {$request->getBody()}\n";
        return Create::promiseFor(new Result(['Fragments' => []]));
    },
]);

$client->listFragments([
    'StreamName' => 'some-stream',
    'FragmentSelector' => [
        'FragmentSelectorType' => 'PRODUCER_TIMESTAMP',
        'TimestampRange' => [
            'StartTimestamp' => new DateTimeImmutable('2024-09-12T10:49:36.500000+00:00'),
            'EndTimestamp'   => new DateTimeImmutable('2024-09-12T10:49:38.833000+00:00'),
        ],
    ],
]);

Before (master):

POST /listFragments
body: {"StreamName":"some-stream","FragmentSelector":{"FragmentSelectorType":"PRODUCER_TIMESTAMP","TimestampRange":{"StartTimestamp":1726138176,"EndTimestamp":1726138178}}}

After:

POST /listFragments
body: {"StreamName":"some-stream","FragmentSelector":{"FragmentSelectorType":"PRODUCER_TIMESTAMP","TimestampRange":{"StartTimestamp":1726138176.5,"EndTimestamp":1726138178.833}}}

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Serialize unixTimestamp and iso8601 request timestamps with the
sub-second precision the caller provided instead of truncating to
whole seconds. Whole-second values are unchanged; rfc822 remains
whole seconds per spec.

Add TimestampShape::formatAsString for string-bound locations
(query, XML, REST headers/querystring/URI) so float epoch values are
not truncated by PHP's `precision` ini setting when cast to string.
* @param mixed $value
*
* @return string[]
* @return array

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this say array<string, string>?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. For context, I just updated this docstring to align with the return type defined by the actual function below which is array. But looks like int, float, or string could be returned so I think array<string, int|float|string> would be more accurate.

I don't want to change the actual time in this PR and would prefer to defer it to a focused PR that audits others that are loose (which I found at least one other).

If you think it should be included now, let me know

@smilkuri
smilkuri merged commit 7860c47 into aws:master Sep 17, 2026
19 of 20 checks passed
@jonathan343
jonathan343 deleted the preserve-subsecond-timestamps branch September 17, 2026 15:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants