diff --git a/Sources/AWSLambdaEvents/Utils/DateWrappers.swift b/Sources/AWSLambdaEvents/Utils/DateWrappers.swift index 81ed03ec..e8432cf8 100644 --- a/Sources/AWSLambdaEvents/Utils/DateWrappers.swift +++ b/Sources/AWSLambdaEvents/Utils/DateWrappers.swift @@ -80,10 +80,15 @@ public struct RFC5322DateTimeCoding: Decodable { public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() - let dateString = try container.decode(String.self) - guard let date = Self.dateFormatter.date(from: dateString) else { + var string = try container.decode(String.self) + // RFC5322 dates sometimes have the alphabetic version of the timezone in brackets after the numeric version. The date formatter + // fails to parse this so we need to remove this before parsing. + if let bracket = string.firstIndex(of: "(") { + string = String(string[string.startIndex ..< bracket].trimmingCharacters(in: .whitespaces)) + } + guard let date = Self.dateFormatter.date(from: string) else { throw DecodingError.dataCorruptedError(in: container, debugDescription: - "Expected date to be in RFC5322 date-time format with fractional seconds, but `\(dateString)` does not forfill format") + "Expected date to be in RFC5322 date-time format with fractional seconds, but `\(string)` does not forfill format") } self.wrappedValue = date } diff --git a/Tests/AWSLambdaEventsTests/Utils/DateWrapperTests.swift b/Tests/AWSLambdaEventsTests/Utils/DateWrapperTests.swift index 88646479..fef0b2ba 100644 --- a/Tests/AWSLambdaEventsTests/Utils/DateWrapperTests.swift +++ b/Tests/AWSLambdaEventsTests/Utils/DateWrapperTests.swift @@ -93,6 +93,32 @@ class DateWrapperTests: XCTestCase { XCTAssertEqual(event?.date.description, "2012-04-05 21:47:37 +0000") } + func testRFC5322DateTimeCodingWrapperWithExtraTimeZoneSuccess() { + struct TestEvent: Decodable { + @RFC5322DateTimeCoding + var date: Date + } + + let json = #"{"date":"Fri, 26 Jun 2020 03:04:03 -0500 (CDT)"}"# + var event: TestEvent? + XCTAssertNoThrow(event = try JSONDecoder().decode(TestEvent.self, from: json.data(using: .utf8)!)) + + XCTAssertEqual(event?.date.description, "2020-06-26 08:04:03 +0000") + } + + func testRFC5322DateTimeCodingWrapperWithAlphabeticTimeZoneSuccess() { + struct TestEvent: Decodable { + @RFC5322DateTimeCoding + var date: Date + } + + let json = #"{"date":"Fri, 26 Jun 2020 03:04:03 CDT"}"# + var event: TestEvent? + XCTAssertNoThrow(event = try JSONDecoder().decode(TestEvent.self, from: json.data(using: .utf8)!)) + + XCTAssertEqual(event?.date.description, "2020-06-26 08:04:03 +0000") + } + func testRFC5322DateTimeCodingWrapperFailure() { struct TestEvent: Decodable { @RFC5322DateTimeCoding diff --git a/readme.md b/readme.md index 91d040ad..377eeec3 100644 --- a/readme.md +++ b/readme.md @@ -337,6 +337,7 @@ AWS Lambda functions can be invoked directly from the AWS Lambda console UI, AWS * [APIGateway Proxy](https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html) * [S3 Events](https://docs.aws.amazon.com/lambda/latest/dg/with-s3.html) +* [SES Events](https://docs.aws.amazon.com/lambda/latest/dg/services-ses.html) * [SNS Events](https://docs.aws.amazon.com/lambda/latest/dg/with-sns.html) * [SQS Events](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html) * [CloudWatch Events](https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents.html)