1515import AWSLambdaRuntime
1616import Dispatch
1717import Foundation
18+ import Logging
19+
1820#if canImport(FoundationNetworking) && canImport(FoundationXML)
1921import FoundationNetworking
2022import FoundationXML
2123#endif
22- import Logging
2324
2425// MARK: - Run Lambda
2526
@@ -71,15 +72,17 @@ struct ExchangeRatesCalculator {
7172
7273 func run( logger: Logger , callback: @escaping ( Result < [ Exchange ] , Swift . Error > ) -> Void ) {
7374 let startDate = Date ( )
74- let months = ( 1 ... 12 ) . map {
75+ let months = ( 1 ... 12 ) . map {
7576 self . calendar. date ( byAdding: DateComponents ( month: - $0) , to: startDate) !
7677 }
7778
78- self . download ( logger: logger,
79- months: months,
80- monthIndex: months. startIndex,
81- currencies: Self . currencies,
82- state: [ : ] ) { result in
79+ self . download (
80+ logger: logger,
81+ months: months,
82+ monthIndex: months. startIndex,
83+ currencies: Self . currencies,
84+ state: [ : ]
85+ ) { result in
8386
8487 switch result {
8588 case . failure( let error) :
@@ -89,7 +92,9 @@ struct ExchangeRatesCalculator {
8992
9093 var result = [ Exchange] ( )
9194 var previousData : [ String : Decimal ? ] = [ : ]
92- for (_, exchangeRateData) in downloadedDataByMonth. filter ( { $1. period != nil } ) . sorted ( by: { $0. key < $1. key } ) {
95+ for (_, exchangeRateData) in downloadedDataByMonth. filter ( { $1. period != nil } ) . sorted ( by: {
96+ $0. key < $1. key
97+ } ) {
9398 for (currencyCode, rate) in exchangeRateData. ratesByCurrencyCode. sorted ( by: { $0. key < $1. key } ) {
9499 if let rate = rate, let currencyEmoji = Self . currenciesEmojies [ currencyCode] {
95100 let change : Exchange . Change
@@ -103,11 +108,15 @@ struct ExchangeRatesCalculator {
103108 default :
104109 change = . unknown
105110 }
106- result. append ( Exchange ( date: exchangeRateData. period!. start,
107- from: . init( symbol: " GBP " , emoji: " 💷 " ) ,
108- to: . init( symbol: currencyCode, emoji: currencyEmoji) ,
109- rate: rate,
110- change: change) )
111+ result. append (
112+ Exchange (
113+ date: exchangeRateData. period!. start,
114+ from: . init( symbol: " GBP " , emoji: " 💷 " ) ,
115+ to: . init( symbol: currencyCode, emoji: currencyEmoji) ,
116+ rate: rate,
117+ change: change
118+ )
119+ )
111120 }
112121 }
113122 previousData = exchangeRateData. ratesByCurrencyCode
@@ -117,12 +126,14 @@ struct ExchangeRatesCalculator {
117126 }
118127 }
119128
120- private func download( logger: Logger ,
121- months: [ Date ] ,
122- monthIndex: Array < Date > . Index ,
123- currencies: [ String ] ,
124- state: [ Date : ExchangeRates ] ,
125- callback: @escaping ( ( Result < [ Date : ExchangeRates ] , Swift . Error > ) -> Void ) ) {
129+ private func download(
130+ logger: Logger ,
131+ months: [ Date ] ,
132+ monthIndex: Array < Date > . Index ,
133+ currencies: [ String ] ,
134+ state: [ Date : ExchangeRates ] ,
135+ callback: @escaping ( ( Result < [ Date : ExchangeRates ] , Swift . Error > ) -> Void )
136+ ) {
126137 if monthIndex == months. count {
127138 return callback ( . success( state) )
128139 }
@@ -146,12 +157,14 @@ struct ExchangeRatesCalculator {
146157 } catch {
147158 return callback ( . failure( error) )
148159 }
149- self . download ( logger: logger,
150- months: months,
151- monthIndex: monthIndex. advanced ( by: 1 ) ,
152- currencies: currencies,
153- state: newState,
154- callback: callback)
160+ self . download (
161+ logger: logger,
162+ months: months,
163+ monthIndex: monthIndex. advanced ( by: 1 ) ,
164+ currencies: currencies,
165+ state: newState,
166+ callback: callback
167+ )
155168 }
156169 dataTask. resume ( )
157170 }
@@ -163,16 +176,18 @@ struct ExchangeRatesCalculator {
163176 dateFormatter. dateFormat = " dd/MMM/yy "
164177 let interval : DateInterval ?
165178 if let period = try document. nodes ( forXPath: " /exchangeRateMonthList/@Period " ) . first? . stringValue,
166- period. count == 26 {
179+ period. count == 26
180+ {
167181 // "01/Sep/2018 to 30/Sep/2018"
168- let startString = period [ period. startIndex ..< period. index ( period. startIndex, offsetBy: 11 ) ]
169- let to = period [ startString. endIndex ..< period. index ( startString. endIndex, offsetBy: 4 ) ]
170- let endString = period [ to. endIndex ..< period. index ( to. endIndex, offsetBy: 11 ) ]
182+ let startString = period [ period. startIndex..< period. index ( period. startIndex, offsetBy: 11 ) ]
183+ let to = period [ startString. endIndex..< period. index ( startString. endIndex, offsetBy: 4 ) ]
184+ let endString = period [ to. endIndex..< period. index ( to. endIndex, offsetBy: 11 ) ]
171185 if let startDate = dateFormatter. date ( from: String ( startString) ) ,
172- let startDay = calendar. dateInterval ( of: . day, for: startDate) ,
173- to == " to " ,
174- let endDate = dateFormatter. date ( from: String ( endString) ) ,
175- let endDay = calendar. dateInterval ( of: . day, for: endDate) {
186+ let startDay = calendar. dateInterval ( of: . day, for: startDate) ,
187+ to == " to " ,
188+ let endDate = dateFormatter. date ( from: String ( endString) ) ,
189+ let endDay = calendar. dateInterval ( of: . day, for: endDate)
190+ {
176191 interval = DateInterval ( start: startDay. start, end: endDay. end)
177192 } else {
178193 interval = nil
@@ -181,16 +196,22 @@ struct ExchangeRatesCalculator {
181196 interval = nil
182197 }
183198
184- let ratesByCurrencyCode : [ String : Decimal ? ] = try Dictionary ( uniqueKeysWithValues: currencyCodes. map {
185- let xpathCurrency = $0. replacingOccurrences ( of: " ' " , with: " ' " )
186- if let rateString = try document. nodes ( forXPath: " /exchangeRateMonthList/exchangeRate/currencyCode[text()=' \( xpathCurrency) ']/../rateNew/text() " ) . first? . stringValue,
187- // We must parse the decimal data using the UK locale, not the system one.
188- let rate = Decimal ( string: rateString, locale: self . locale) {
189- return ( $0, rate)
190- } else {
191- return ( $0, nil )
199+ let ratesByCurrencyCode : [ String : Decimal ? ] = try Dictionary (
200+ uniqueKeysWithValues: currencyCodes. map {
201+ let xpathCurrency = $0. replacingOccurrences ( of: " ' " , with: " ' " )
202+ if let rateString = try document. nodes (
203+ forXPath:
204+ " /exchangeRateMonthList/exchangeRate/currencyCode[text()=' \( xpathCurrency) ']/../rateNew/text() "
205+ ) . first? . stringValue,
206+ // We must parse the decimal data using the UK locale, not the system one.
207+ let rate = Decimal ( string: rateString, locale: self . locale)
208+ {
209+ return ( $0, rate)
210+ } else {
211+ return ( $0, nil )
212+ }
192213 }
193- } )
214+ )
194215
195216 return ( period: interval, ratesByCurrencyCode: ratesByCurrencyCode)
196217 }
0 commit comments