15
15
import AWSLambdaRuntime
16
16
import Dispatch
17
17
import Foundation
18
+ import Logging
19
+
18
20
#if canImport(FoundationNetworking) && canImport(FoundationXML)
19
21
import FoundationNetworking
20
22
import FoundationXML
21
23
#endif
22
- import Logging
23
24
24
25
// MARK: - Run Lambda
25
26
@@ -71,15 +72,17 @@ struct ExchangeRatesCalculator {
71
72
72
73
func run( logger: Logger , callback: @escaping ( Result < [ Exchange ] , Swift . Error > ) -> Void ) {
73
74
let startDate = Date ( )
74
- let months = ( 1 ... 12 ) . map {
75
+ let months = ( 1 ... 12 ) . map {
75
76
self . calendar. date ( byAdding: DateComponents ( month: - $0) , to: startDate) !
76
77
}
77
78
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
83
86
84
87
switch result {
85
88
case . failure( let error) :
@@ -89,7 +92,9 @@ struct ExchangeRatesCalculator {
89
92
90
93
var result = [ Exchange] ( )
91
94
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
+ } ) {
93
98
for (currencyCode, rate) in exchangeRateData. ratesByCurrencyCode. sorted ( by: { $0. key < $1. key } ) {
94
99
if let rate = rate, let currencyEmoji = Self . currenciesEmojies [ currencyCode] {
95
100
let change : Exchange . Change
@@ -103,11 +108,15 @@ struct ExchangeRatesCalculator {
103
108
default :
104
109
change = . unknown
105
110
}
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
+ )
111
120
}
112
121
}
113
122
previousData = exchangeRateData. ratesByCurrencyCode
@@ -117,12 +126,14 @@ struct ExchangeRatesCalculator {
117
126
}
118
127
}
119
128
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
+ ) {
126
137
if monthIndex == months. count {
127
138
return callback ( . success( state) )
128
139
}
@@ -146,12 +157,14 @@ struct ExchangeRatesCalculator {
146
157
} catch {
147
158
return callback ( . failure( error) )
148
159
}
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
+ )
155
168
}
156
169
dataTask. resume ( )
157
170
}
@@ -163,16 +176,18 @@ struct ExchangeRatesCalculator {
163
176
dateFormatter. dateFormat = " dd/MMM/yy "
164
177
let interval : DateInterval ?
165
178
if let period = try document. nodes ( forXPath: " /exchangeRateMonthList/@Period " ) . first? . stringValue,
166
- period. count == 26 {
179
+ period. count == 26
180
+ {
167
181
// "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 ) ]
171
185
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
+ {
176
191
interval = DateInterval ( start: startDay. start, end: endDay. end)
177
192
} else {
178
193
interval = nil
@@ -181,16 +196,22 @@ struct ExchangeRatesCalculator {
181
196
interval = nil
182
197
}
183
198
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
+ }
192
213
}
193
- } )
214
+ )
194
215
195
216
return ( period: interval, ratesByCurrencyCode: ratesByCurrencyCode)
196
217
}
0 commit comments