@@ -373,6 +373,94 @@ public void writeString(Schema schema, String value) {
373373 assertThat (set [1 ], equalTo (schema .member ("a" )));
374374 }
375375
376+ @ Test
377+ public void parsesIsoStringForTimestampMember () {
378+ var schema = Schema .structureBuilder (ShapeId .from ("foo#Bar" ))
379+ .putMember ("when" , PreludeSchemas .TIMESTAMP )
380+ .build ();
381+ var document = Document .ofObject (Map .of ("when" , "2024-01-01T00:00:00Z" ));
382+
383+ var sd = StructDocument .of (schema , document , ShapeId .from ("smithy.example#S" ));
384+
385+ var when = sd .getMember ("when" );
386+ assertThat (when .type (), is (ShapeType .TIMESTAMP ));
387+ assertThat (when .asTimestamp (), equalTo (Instant .parse ("2024-01-01T00:00:00Z" )));
388+ }
389+
390+ @ Test
391+ public void readsEpochNumberForTimestampMember () {
392+ var schema = Schema .structureBuilder (ShapeId .from ("foo#Bar" ))
393+ .putMember ("when" , PreludeSchemas .TIMESTAMP )
394+ .build ();
395+ var document = Document .ofObject (Map .of ("when" , 1704067200 ));
396+
397+ var sd = StructDocument .of (schema , document , ShapeId .from ("smithy.example#S" ));
398+
399+ assertThat (sd .getMember ("when" ).asTimestamp (), equalTo (Instant .parse ("2024-01-01T00:00:00Z" )));
400+ }
401+
402+ @ Test
403+ public void parsesIsoStringsForNestedTimestamps () {
404+ var model = Model .assembler ()
405+ .addUnparsedModel ("test.smithy" , """
406+ $version: "2"
407+ namespace smithy.example
408+
409+ structure Foo {
410+ items: ItemList
411+ }
412+
413+ list ItemList {
414+ member: Item
415+ }
416+
417+ structure Item {
418+ when: Timestamp
419+ }
420+ """ )
421+ .assemble ()
422+ .unwrap ();
423+ var converter = new SchemaConverter (model );
424+ var schema = converter .getSchema (model .expectShape (ShapeId .from ("smithy.example#Foo" )));
425+
426+ var input = Document .ofObject (Map .of (
427+ "items" ,
428+ List .of (
429+ Map .of ("when" , "2024-01-01T00:00:00Z" ),
430+ Map .of ("when" , "2024-06-22T12:00:00Z" ))));
431+ var sd = StructDocument .of (schema , input );
432+
433+ var items = sd .getMember ("items" ).asList ();
434+ assertThat (items , hasSize (2 ));
435+ assertThat (items .get (0 ).getMember ("when" ).asTimestamp (), equalTo (Instant .parse ("2024-01-01T00:00:00Z" )));
436+ assertThat (items .get (1 ).getMember ("when" ).asTimestamp (), equalTo (Instant .parse ("2024-06-22T12:00:00Z" )));
437+ }
438+
439+ @ Test
440+ public void ignoresTimestampFormatTraitWhenCoercingInput () {
441+ // @timestampFormat is a wire-serialization concern; the protocol-agnostic input model always treats
442+ // a string as date-time (ISO-8601), regardless of any trait on the member.
443+ var model = Model .assembler ()
444+ .addUnparsedModel ("test.smithy" , """
445+ $version: "2"
446+ namespace smithy.example
447+
448+ structure Foo {
449+ @timestampFormat("epoch-seconds")
450+ when: Timestamp
451+ }
452+ """ )
453+ .assemble ()
454+ .unwrap ();
455+ var converter = new SchemaConverter (model );
456+ var schema = converter .getSchema (model .expectShape (ShapeId .from ("smithy.example#Foo" )));
457+
458+ var input = Document .ofObject (Map .of ("when" , "2024-01-01T00:00:00Z" ));
459+ var sd = StructDocument .of (schema , input );
460+
461+ assertThat (sd .getMember ("when" ).asTimestamp (), equalTo (Instant .parse ("2024-01-01T00:00:00Z" )));
462+ }
463+
376464 @ Test
377465 public void convertDocumentPassesThroughDataStream () {
378466 var model = Model .assembler ()
0 commit comments