Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add timezone to dateformatter #500

Merged
merged 8 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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