From 2e9fed6cc97d912cc508487b95f6794f21cf442d Mon Sep 17 00:00:00 2001 From: Chase Coalwell <782571+srchase@users.noreply.github.com> Date: Mon, 30 Jan 2023 16:29:49 -0700 Subject: [PATCH] Clients parse datetime offsets (#681) --- .../integration/DocumentMemberDeserVisitor.java | 3 ++- .../integration/HttpBindingProtocolGenerator.java | 2 +- .../integration/HttpProtocolGeneratorUtils.java | 15 ++++++++++++--- .../DocumentMemberDeserVisitorTest.java | 6 ++++++ .../HttpProtocolGeneratorUtilsTest.java | 10 ++++++---- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/DocumentMemberDeserVisitor.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/DocumentMemberDeserVisitor.java index 2fd6a16584e..591094d192f 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/DocumentMemberDeserVisitor.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/DocumentMemberDeserVisitor.java @@ -241,7 +241,8 @@ public String timestampShape(TimestampShape shape) { Location.DOCUMENT, shape, format, - requiresNumericEpochSecondsInPayload()); + requiresNumericEpochSecondsInPayload(), + context.getSettings().generateClient()); } @Override diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpBindingProtocolGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpBindingProtocolGenerator.java index 22074d99802..fc8226f4a9f 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpBindingProtocolGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpBindingProtocolGenerator.java @@ -2484,7 +2484,7 @@ private String getOutputValue( Format format = httpIndex.determineTimestampFormat(member, bindingType, getDocumentTimestampFormat()); return HttpProtocolGeneratorUtils.getTimestampOutputParam( context.getWriter(), dataSource, bindingType, member, format, - requiresNumericEpochSecondsInPayload()); + requiresNumericEpochSecondsInPayload(), context.getSettings().generateClient()); } else if (target instanceof BlobShape) { return getBlobOutputParam(bindingType, dataSource); } else if (target instanceof CollectionShape) { diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpProtocolGeneratorUtils.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpProtocolGeneratorUtils.java index 3cd76cafb12..7da67af1caf 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpProtocolGeneratorUtils.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpProtocolGeneratorUtils.java @@ -103,6 +103,7 @@ public static String getTimestampInputParam( * @param format The timestamp format to provide. * @param requireNumericEpochSecondsInPayload if true, paylaod epoch seconds are not allowed to be coerced * from strings. + * @param isClient true if generating a client. * @return Returns a value or expression of the output timestamp. */ public static String getTimestampOutputParam(TypeScriptWriter writer, @@ -110,14 +111,22 @@ public static String getTimestampOutputParam(TypeScriptWriter writer, Location bindingType, Shape shape, Format format, - boolean requireNumericEpochSecondsInPayload) { + boolean requireNumericEpochSecondsInPayload, + boolean isClient) { // This has always explicitly wrapped the dataSource in "new Date(..)", so it could never generate // an expression that evaluates to null. Codegen relies on this. writer.addImport("expectNonNull", "__expectNonNull", "@aws-sdk/smithy-client"); switch (format) { case DATE_TIME: - writer.addImport("parseRfc3339DateTime", "__parseRfc3339DateTime", "@aws-sdk/smithy-client"); - return String.format("__expectNonNull(__parseRfc3339DateTime(%s))", dataSource); + // Clients should be able to handle offsets and normalize the datetime to an offset of zero. + if (isClient) { + writer.addImport("parseRfc3339DateTimeWithOffset", "__parseRfc3339DateTimeWithOffset", + "@aws-sdk/smithy-client"); + return String.format("__expectNonNull(__parseRfc3339DateTimeWithOffset(%s))", dataSource); + } else { + writer.addImport("parseRfc3339DateTime", "__parseRfc3339DateTime", "@aws-sdk/smithy-client"); + return String.format("__expectNonNull(__parseRfc3339DateTime(%s))", dataSource); + } case HTTP_DATE: writer.addImport("parseRfc7231DateTime", "__parseRfc7231DateTime", "@aws-sdk/smithy-client"); return String.format("__expectNonNull(__parseRfc7231DateTime(%s))", dataSource); diff --git a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/DocumentMemberDeserVisitorTest.java b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/DocumentMemberDeserVisitorTest.java index 2277d51c73d..e203f9fa17f 100644 --- a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/DocumentMemberDeserVisitorTest.java +++ b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/DocumentMemberDeserVisitorTest.java @@ -37,7 +37,9 @@ import software.amazon.smithy.model.traits.MediaTypeTrait; import software.amazon.smithy.model.traits.TimestampFormatTrait; import software.amazon.smithy.model.traits.TimestampFormatTrait.Format; +import software.amazon.smithy.typescript.codegen.TypeScriptSettings; import software.amazon.smithy.typescript.codegen.TypeScriptWriter; +import software.amazon.smithy.typescript.codegen.TypeScriptSettings.ArtifactType; import software.amazon.smithy.typescript.codegen.integration.ProtocolGenerator.GenerationContext; import software.amazon.smithy.utils.ListUtils; @@ -46,12 +48,16 @@ public class DocumentMemberDeserVisitorTest { private static final String PROTOCOL = "TestProtocol"; private static final Format FORMAT = Format.EPOCH_SECONDS; private static GenerationContext mockContext; + private static TypeScriptSettings mockSettings; static { mockContext = new GenerationContext(); + mockSettings = new TypeScriptSettings(); mockContext.setProtocolName(PROTOCOL); mockContext.setSymbolProvider(new MockProvider()); mockContext.setWriter(new TypeScriptWriter("foo")); + mockSettings.setArtifactType(ArtifactType.SSDK); + mockContext.setSettings(mockSettings); } @ParameterizedTest diff --git a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/HttpProtocolGeneratorUtilsTest.java b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/HttpProtocolGeneratorUtilsTest.java index d48b47ed98c..aa3f899a4a9 100644 --- a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/HttpProtocolGeneratorUtilsTest.java +++ b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/HttpProtocolGeneratorUtilsTest.java @@ -41,14 +41,16 @@ public void givesCorrectTimestampDeserialization() { TimestampShape shape = TimestampShape.builder().id("com.smithy.example#Foo").build(); TypeScriptWriter writer = new TypeScriptWriter("foo"); + assertThat("__expectNonNull(__parseRfc3339DateTimeWithOffset(" + DATA_SOURCE + "))", + equalTo(HttpProtocolGeneratorUtils.getTimestampOutputParam(writer, DATA_SOURCE, Location.DOCUMENT, shape, Format.DATE_TIME, false, true))); assertThat("__expectNonNull(__parseRfc3339DateTime(" + DATA_SOURCE + "))", - equalTo(HttpProtocolGeneratorUtils.getTimestampOutputParam(writer, DATA_SOURCE, Location.DOCUMENT, shape, Format.DATE_TIME, false))); + equalTo(HttpProtocolGeneratorUtils.getTimestampOutputParam(writer, DATA_SOURCE, Location.DOCUMENT, shape, Format.DATE_TIME, false, false))); assertThat("__expectNonNull(__parseEpochTimestamp(__expectNumber(" + DATA_SOURCE + ")))", - equalTo(HttpProtocolGeneratorUtils.getTimestampOutputParam(writer, DATA_SOURCE, Location.DOCUMENT, shape, Format.EPOCH_SECONDS, true))); + equalTo(HttpProtocolGeneratorUtils.getTimestampOutputParam(writer, DATA_SOURCE, Location.DOCUMENT, shape, Format.EPOCH_SECONDS, true, false))); assertThat("__expectNonNull(__parseEpochTimestamp(" + DATA_SOURCE + "))", - equalTo(HttpProtocolGeneratorUtils.getTimestampOutputParam(writer, DATA_SOURCE, Location.DOCUMENT, shape, Format.EPOCH_SECONDS, false))); + equalTo(HttpProtocolGeneratorUtils.getTimestampOutputParam(writer, DATA_SOURCE, Location.DOCUMENT, shape, Format.EPOCH_SECONDS, false, false))); assertThat("__expectNonNull(__parseRfc7231DateTime(" + DATA_SOURCE + "))", - equalTo(HttpProtocolGeneratorUtils.getTimestampOutputParam(writer, DATA_SOURCE, Location.DOCUMENT, shape, Format.HTTP_DATE, false))); + equalTo(HttpProtocolGeneratorUtils.getTimestampOutputParam(writer, DATA_SOURCE, Location.DOCUMENT, shape, Format.HTTP_DATE, false, false))); } @Test