Skip to content

Commit

Permalink
Add timezone to dateformatter (#500)
Browse files Browse the repository at this point in the history
  • Loading branch information
mltbnz authored Mar 5, 2024
1 parent 1b8b6f0 commit 3845d3c
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 22 deletions.
4 changes: 4 additions & 0 deletions CriticalMaps.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
7327344D277118670007579E /* TwitterFeaturePreviewApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwitterFeaturePreviewApp.swift; sourceTree = "<group>"; };
7347AB262A27BE2A00BCA949 /* ChatFeature.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = ChatFeature.xctestplan; sourceTree = "<group>"; };
7347AB272A27C0A900BCA949 /* MapFeature.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = MapFeature.xctestplan; sourceTree = "<group>"; };
7355D2E42B91C4350097DD42 /* NextRideFeatureTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = NextRideFeatureTests.xctestplan; sourceTree = "<group>"; };
73654C6B26C85FCF004BE38B /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
7369207C28D0D92100EA0584 /* SnapshotTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = SnapshotTests.xctestplan; sourceTree = "<group>"; };
738214EF271F49AB009847C7 /* appIcon-5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "appIcon-5.png"; sourceTree = "<group>"; };
Expand All @@ -51,6 +52,7 @@
73CF5FF1263EB0A6001925A3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
73CF5FF6263EB0A6001925A3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
73EB0310263F23A100941D57 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
73F010D82B94A19700C2B613 /* LisbonPortugal.gpx */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = LisbonPortugal.gpx; sourceTree = "<group>"; };
73FD0B302779F5500061539D /* GuideFeaturePreview.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GuideFeaturePreview.app; sourceTree = BUILT_PRODUCTS_DIR; };
73FD0B322779F5500061539D /* GuideFeaturePreviewApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuideFeaturePreviewApp.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -126,6 +128,7 @@
7347AB282A27C0CA00BCA949 /* Testplans */ = {
isa = PBXGroup;
children = (
7355D2E42B91C4350097DD42 /* NextRideFeatureTests.xctestplan */,
7347AB272A27C0A900BCA949 /* MapFeature.xctestplan */,
7347AB262A27BE2A00BCA949 /* ChatFeature.xctestplan */,
7369207C28D0D92100EA0584 /* SnapshotTests.xctestplan */,
Expand All @@ -150,6 +153,7 @@
73CF5FB9263EAF5B001925A3 = {
isa = PBXGroup;
children = (
73F010D82B94A19700C2B613 /* LisbonPortugal.gpx */,
73BABF82277B0A2900D9790F /* CHANGELOG.md */,
73BABF83277B0A2900D9790F /* README.md */,
732734462771172C0007579E /* CriticalMapsKit */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:../Testplans/NextRideFeatureTests.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "NextRideFeatureTests"
BuildableName = "NextRideFeatureTests"
BlueprintName = "NextRideFeatureTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
18 changes: 12 additions & 6 deletions CriticalMapsKit/Sources/Helpers/DateFormatter+Additions.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ComposableArchitecture
import Foundation

public extension DateFormatter {
Expand Down Expand Up @@ -34,16 +35,21 @@ extension Date.FormatStyle {
locale: .autoupdatingCurrent
)

public static let localeAwareShortDate = Self(
date: .numeric,
time: .omitted,
locale: .autoupdatingCurrent
)
public static let localeAwareShortDate: Self = {
@Dependency(\.timeZone) var timezone
return Self(
date: .numeric,
time: .omitted,
locale: .autoupdatingCurrent,
timeZone: timezone
)
}()

public static let localeAwareShortTime = Self(
date: .omitted,
time: .shortened,
locale: .autoupdatingCurrent
locale: .autoupdatingCurrent,
timeZone: .germany
)

public static func chatTime(_ cal: Calendar = .autoupdatingCurrent) -> Self {
Expand Down
26 changes: 26 additions & 0 deletions CriticalMapsKit/Sources/Helpers/Timezone+Extras.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Foundation

public extension TimeZone {
// Europe
static let germany = TimeZone(identifier: "Europe/Berlin")!
static let gmt = TimeZone(identifier: "GMT")!
static let spain = TimeZone(identifier: "Europe/Madrid")!
static let france = TimeZone(identifier: "Europe/Paris")!
static let greece = TimeZone(identifier: "Europe/Athens")!

// America
static let ecuador = TimeZone(identifier: "America/Guayaquil")!
static let cuba = TimeZone(identifier: "America/Havana")!

// Africa
static let egypt = TimeZone(identifier: "Africa/Cairo")!
static let southAfrica = TimeZone(identifier: "Africa/Johannesburg")!

// Asia
static let india = TimeZone(identifier: "Asia/Kolkata")!
static let japan = TimeZone(identifier: "Asia/Tokyo")!

// USA
static let newYork = TimeZone(identifier: "America/New_York")!
static let losAngeles = TimeZone(identifier: "America/Los_Angeles")!
}
5 changes: 3 additions & 2 deletions CriticalMapsKit/Sources/NextRideFeature/NextRideCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public struct NextRideFeature: ReducerProtocol {
@Dependency(\.mainQueue) public var mainQueue
@Dependency(\.coordinateObfuscator) public var coordinateObfuscator
@Dependency(\.isNetworkAvailable) public var isNetworkAvailable
@Dependency(\.calendar) public var calendar

public struct State: Equatable {
public init(nextRide: Ride? = nil) {
Expand Down Expand Up @@ -70,6 +71,7 @@ public struct NextRideFeature: ReducerProtocol {
case let .nextRideResponse(.failure(error)):
logger.error("Get next ride failed 🛑 with error: \(error)")
return .none

case let .nextRideResponse(.success(rides)):
guard !rides.isEmpty else {
logger.info("Rides array is empty")
Expand Down Expand Up @@ -101,7 +103,7 @@ public struct NextRideFeature: ReducerProtocol {
return byDate
}

if Calendar.current.isDate(lhs.dateTime, inSameDayAs: rhs.dateTime) {
if calendar.isDate(lhs.dateTime, inSameDayAs: rhs.dateTime) {
return lhsCoordinate.distance(from: userLocation) < rhsCoordinate.distance(from: userLocation)
} else {
return byDate
Expand All @@ -113,7 +115,6 @@ public struct NextRideFeature: ReducerProtocol {
logger.info("No upcoming events after filter")
return .none
}

return EffectTask(value: .setNextRide(filteredRide))

case let .setNextRide(ride):
Expand Down
26 changes: 23 additions & 3 deletions CriticalMapsKit/Tests/NextRideFeatureTests/NextRideCoreTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ final class NextRideCoreTests: XCTestCase {
let now = {
Calendar.current.date(
from: .init(
timeZone: .init(secondsFromGMT: 0),
timeZone: .germany,
year: 2022,
month: 3,
day: 25,
Expand Down Expand Up @@ -43,6 +43,26 @@ final class NextRideCoreTests: XCTestCase {
)
}

var berlinNow: Ride {
Ride(
id: 0,
slug: nil,
title: "CriticalMaps Berlin",
description: nil,
dateTime: now(),
location: nil,
latitude: 53.1235,
longitude: 13.4234,
estimatedParticipants: nil,
estimatedDistance: nil,
estimatedDuration: nil,
enabled: true,
disabledReason: nil,
disabledReasonMessage: nil,
rideType: .criticalMass
)
}

var falkensee: Ride {
Ride(
id: 0,
Expand All @@ -64,7 +84,6 @@ final class NextRideCoreTests: XCTestCase {
}

var rides: [Ride] { [berlin, falkensee] }

let coordinate = Coordinate(latitude: 53.1234, longitude: 13.4233)

func test_disabledNextRideFeature_shouldNotRequestRides() async {
Expand All @@ -87,7 +106,7 @@ final class NextRideCoreTests: XCTestCase {
await store.receive(.nextRideResponse(.success([])))
}

func test_getNextRide_shouldReturnMockRide() async {
func test_getRides_shouldUpdateRidesInUserTimezone() async {
let store = TestStore(
initialState: .init(),
reducer: NextRideFeature()
Expand Down Expand Up @@ -343,6 +362,7 @@ final class NextRideCoreTests: XCTestCase {
.encoded()
}
store.dependencies.date = .constant(now())
store.dependencies.calendar = .autoupdatingCurrent
store.dependencies.isNetworkAvailable = true

// then
Expand Down
90 changes: 90 additions & 0 deletions CriticalMapsKit/Tests/NextRideFeatureTests/RideTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import ComposableArchitecture
import Helpers
import SharedModels
import XCTest

final class RideTests: XCTestCase {
func test_rideInGMTTimezone() {
// arrange
let ride = Ride.mock()

// act
withDependencies {
$0.timeZone = .gmt
} operation: {
XCTAssertEqual(
"20:00",
ride.dateTime.humanReadableTime
)
}
}

func test_rideInGermanTimezone() {
// arrange
let ride = Ride.mock()

// act
withDependencies {
$0.timeZone = .germany
} operation: {
XCTAssertEqual(
"20:00",
ride.dateTime.humanReadableTime
)
}
}

func test_rideInGreeceTimezone() {
// arrange
let ride = Ride.mock()

// act
withDependencies {
$0.timeZone = .greece
$0.calendar = .init(identifier: .gregorian)
} operation: {
XCTAssertEqual(
"20:00",
ride.dateTime.humanReadableTime
)
}
}

func test_rideInEcuadorTimezone() {
// arrange
let ride = Ride.mock()

// act
withDependencies {
$0.timeZone = .ecuador
$0.calendar = .init(identifier: .gregorian)
} operation: {
XCTAssertEqual(
"20:00",
ride.dateTime.humanReadableTime
)
}
}
}

extension Ride {
static func mock() -> Self {
Self(
id: 0,
slug: nil,
title: "CriticalMaps Berlin",
description: nil,
dateTime: Date(timeIntervalSince1970: 1711738800),
location: nil,
latitude: 53.1235,
longitude: 13.4234,
estimatedParticipants: nil,
estimatedDistance: nil,
estimatedDuration: nil,
enabled: true,
disabledReason: nil,
disabledReasonMessage: nil,
rideType: .criticalMass
)
}
}
8 changes: 8 additions & 0 deletions LisbonPortugal.gpx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<gpx version="1.1" creator="Xcode">
<wpt lat="38.7223" lon="-9.1393">
<name>Cupertino</name>
<time>2014-09-24T14:55:37Z</time>
</wpt>

</gpx>
42 changes: 42 additions & 0 deletions Testplans/NextRideFeatureTests.xctestplan
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"configurations" : [
{
"id" : "EC875105-37D8-413B-989B-09862018C3C9",
"name" : "Test Scheme Action",
"options" : {
"language" : "en",
"region" : "GB"
}
},
{
"id" : "1858BF7A-D057-468A-B31F-AD3EB6637E6E",
"name" : "Configuration 2",
"options" : {
"environmentVariableEntries" : [
{
"key" : "setenv(\"TZ\", identifier, 1)",
"value" : ""
}
]
}
}
],
"defaultOptions" : {
"language" : "en",
"locationScenario" : {
"identifier" : "London, England",
"referenceType" : "built-in"
},
"region" : "GB"
},
"testTargets" : [
{
"target" : {
"containerPath" : "container:",
"identifier" : "NextRideFeatureTests",
"name" : "NextRideFeatureTests"
}
}
],
"version" : 1
}
Loading

0 comments on commit 3845d3c

Please sign in to comment.