Created
August 15, 2019 09:13
-
-
Save larryonoff/17406518424282eb107c3e083917f9dd to your computer and use it in GitHub Desktop.
store
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import StoreKit | |
final class ProductPriceConverter { | |
func convertPrice( | |
_ price: NSDecimalNumber, | |
from fromUnit: SKProduct.PeriodUnit, | |
fromNumberOfUnits: Int, | |
to toUnit: SKProduct.PeriodUnit, | |
toNumberOfUnits: Int | |
) -> NSDecimalNumber { | |
switch (fromUnit, toUnit) { | |
case (.day, .day): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.day, .week): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.multiplying(by: NSDecimalNumber(value: 7)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.day, .month): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.multiplying(by: NSDecimalNumber(value: 30)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.day, .year): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.multiplying(by: NSDecimalNumber(value: 365)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.week, .day): | |
return price.dividing(by: NSDecimalNumber(value: 7)) | |
case (.week, .week): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.week, .month): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.multiplying(by: NSDecimalNumber(value: 4.345)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.week, .year): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.multiplying(by: NSDecimalNumber(value: 52.143)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.month, .day): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.dividing(by: NSDecimalNumber(value: 30)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.month, .week): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.dividing(by: NSDecimalNumber(value: 4.345)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.month, .month): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.month, .year): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.multiplying(by: NSDecimalNumber(value: 12)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.year, .day): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.dividing(by: NSDecimalNumber(value: 365)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.year, .week): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.dividing(by: NSDecimalNumber(value: 52.143)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.year, .month): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.dividing(by: NSDecimalNumber(value: 12)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
case (.year, .year): | |
return price | |
.dividing(by: NSDecimalNumber(value: fromNumberOfUnits)) | |
.multiplying(by: NSDecimalNumber(value: toNumberOfUnits)) | |
@unknown default: | |
fatalError() | |
} | |
} | |
func convertPrice( | |
of product: SKProduct, | |
to unit: SKProduct.PeriodUnit, | |
numberOfUnits: Int | |
) -> NSDecimalNumber? { | |
guard let subscriptionPeriod = product.subscriptionPeriod else { return nil } | |
return convertPrice( | |
product.price, | |
from: subscriptionPeriod.unit, | |
fromNumberOfUnits: subscriptionPeriod.numberOfUnits, | |
to: unit, | |
toNumberOfUnits: numberOfUnits) | |
} | |
func discount( | |
of product: SKProduct, | |
inRelationTo toProduct: SKProduct, | |
unit: SKProduct.PeriodUnit | |
) -> NSDecimalNumber? { | |
guard let price = convertPrice( | |
of: product, | |
to: .year, | |
numberOfUnits: 1) else { | |
return nil | |
} | |
guard let toPrice = convertPrice( | |
of: toProduct, | |
to: .year, | |
numberOfUnits: 1) else { | |
return nil | |
} | |
let decimalHandler = NSDecimalNumberHandler( | |
roundingMode: .bankers, | |
scale: 2, | |
raiseOnExactness: false, | |
raiseOnOverflow: false, | |
raiseOnUnderflow: false, | |
raiseOnDivideByZero: false) | |
let ratio = price | |
.dividing(by: toPrice) | |
.rounding(accordingToBehavior: decimalHandler) | |
return NSDecimalNumber(value: 1).subtracting(ratio) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment