Skip to content

Commit

Permalink
Show event time in local timezone
Browse files Browse the repository at this point in the history
  • Loading branch information
pakerwreah committed Mar 1, 2023
1 parent f44df92 commit 1775e5b
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 26 deletions.
18 changes: 15 additions & 3 deletions Calendr.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
3442769A269B5CA4004CFE1C /* UITestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34427699269B5CA4004CFE1C /* UITestCase.swift */; };
3449402E25C348B20020E664 /* GeneralSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3449402D25C348B20020E664 /* GeneralSettingsViewController.swift */; };
3449403225C348C70020E664 /* CalendarPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3449403125C348C70020E664 /* CalendarPickerViewController.swift */; };
344A59DB29AEBBBF004F0452 /* EventUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344A59DA29AEBBBF004F0452 /* EventUtils.swift */; };
3453E6FD28386A84002DCC3C /* Bool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3453E6FC28386A84002DCC3C /* Bool.swift */; };
3453E6FF28393943002DCC3C /* ContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3453E6FE28393943002DCC3C /* ContextMenu.swift */; };
345DD97326920D1B00294D90 /* CalendarViewPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 345DD97226920D1B00294D90 /* CalendarViewPreview.swift */; };
Expand Down Expand Up @@ -198,6 +199,7 @@
3442769B269B5CA4004CFE1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3449402D25C348B20020E664 /* GeneralSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsViewController.swift; sourceTree = "<group>"; };
3449403125C348C70020E664 /* CalendarPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarPickerViewController.swift; sourceTree = "<group>"; };
344A59DA29AEBBBF004F0452 /* EventUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventUtils.swift; sourceTree = "<group>"; };
3453E6FC28386A84002DCC3C /* Bool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bool.swift; sourceTree = "<group>"; };
3453E6FE28393943002DCC3C /* ContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenu.swift; sourceTree = "<group>"; };
345DD97226920D1B00294D90 /* CalendarViewPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarViewPreview.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -429,6 +431,14 @@
path = CalendrUITests;
sourceTree = "<group>";
};
344A59D929AEBBB0004F0452 /* EventUtils */ = {
isa = PBXGroup;
children = (
344A59DA29AEBBBF004F0452 /* EventUtils.swift */,
);
path = EventUtils;
sourceTree = "<group>";
};
347D0F8B25952F89002451EC = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -661,9 +671,10 @@
34ABB9E429A12A720021F3CF /* Events */ = {
isa = PBXGroup;
children = (
34ABB9E129A129F00021F3CF /* ContextMenu */,
34ABB9DE29A129D10021F3CF /* EventDetails */,
34ABB9E329A129FE0021F3CF /* EventList */,
34ABB9E129A129F00021F3CF /* ContextMenu */,
344A59D929AEBBB0004F0452 /* EventUtils */,
);
path = Events;
sourceTree = "<group>";
Expand Down Expand Up @@ -919,6 +930,7 @@
34934CD628E69520009635D4 /* Prefs+UserDefaults.swift in Sources */,
34FD09D925AE269600AAAAE2 /* DateProvider.swift in Sources */,
34D25E4A292F9E2100557E70 /* ImageButton.swift in Sources */,
344A59DB29AEBBBF004F0452 /* EventUtils.swift in Sources */,
34AC60C626925FA5005312B6 /* PreviewExtensions.swift in Sources */,
3477F3CE25FAE56A008EA888 /* EventDetailsViewModel.swift in Sources */,
3487A43C25E70F5B00FCC7D7 /* NextEventView.swift in Sources */,
Expand Down Expand Up @@ -1227,7 +1239,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.9.0;
MARKETING_VERSION = 1.9.1;
PRODUCT_BUNDLE_IDENTIFIER = br.paker.Calendr;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Calendr/Config/Calendr-Bridging-Header.h";
Expand All @@ -1253,7 +1265,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.9.0;
MARKETING_VERSION = 1.9.1;
PRODUCT_BUNDLE_IDENTIFIER = br.paker.Calendr;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Calendr/Config/Calendr-Bridging-Header.h";
Expand Down
8 changes: 7 additions & 1 deletion Calendr/Events/EventDetails/EventDetailsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,13 @@ class EventDetailsViewModel {
end = event.end
}

duration = formatter.string(from: event.start, to: end)
duration = EventUtils.duration(
from: event.start,
to: end,
timeZone: event.timeZone,
formatter: formatter,
isMeeting: event.isMeeting
)
}
}

Expand Down
8 changes: 7 additions & 1 deletion Calendr/Events/EventList/EventViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,13 @@ class EventViewModel {
end = event.end
}

duration = formatter.string(from: event.start, to: end)
duration = EventUtils.duration(
from: event.start,
to: end,
timeZone: event.timeZone,
formatter: formatter,
isMeeting: event.isMeeting
)

} else if !showTime {

Expand Down
34 changes: 34 additions & 0 deletions Calendr/Events/EventUtils/EventUtils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// EventUtils.swift
// Calendr
//
// Created by Paker on 28/02/23.
//

import Foundation

enum EventUtils {

static func duration(
from start: Date,
to end: Date,
timeZone: TimeZone?,
formatter: DateIntervalFormatter,
isMeeting: Bool
) -> String {

guard
!isMeeting,
let timeZone, timeZone != formatter.timeZone,
let tz_abbreviation = timeZone.abbreviation(for: start)
else {
return formatter.string(from: start, to: end)
}

let origTimeZone = formatter.timeZone
defer { formatter.timeZone = origTimeZone }
formatter.timeZone = timeZone

return "\(formatter.string(from: start, to: end)) (\(tz_abbreviation))"
}
}
24 changes: 22 additions & 2 deletions Calendr/Mocks/Factories/EventModel+Factory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ extension EventModel {
isAllDay: Bool = false,
type: EventType = .event(.accepted),
calendar: CalendarModel = .make(),
participants: [Participant] = []
participants: [Participant] = [],
timeZone: TimeZone? = nil
) -> EventModel {

.init(
Expand All @@ -36,7 +37,26 @@ extension EventModel {
isAllDay: isAllDay || type.isBirthday,
type: type,
calendar: calendar,
participants: participants
participants: participants,
timeZone: timeZone
)
}
}

extension Participant {

static func make(
name: String = "",
status: EventStatus = .unknown,
isOrganizer: Bool = false,
isCurrentUser: Bool = false
) -> Participant {

.init(
name: name,
status: status,
isOrganizer: isOrganizer,
isCurrentUser: isCurrentUser
)
}
}
Expand Down
3 changes: 3 additions & 0 deletions Calendr/Models/EventModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct EventModel: Equatable {
let type: EventType
let calendar: CalendarModel
let participants: [Participant]
let timeZone: TimeZone?
}

enum EventStatus: Comparable {
Expand Down Expand Up @@ -60,6 +61,8 @@ extension EventModel {
func range(using dateProvider: DateProviding) -> DateRange { .init(start: start, end: end, dateProvider: dateProvider) }

var status: EventStatus { if case .event(let status) = type { return status } else { return .unknown } }

var isMeeting: Bool { !participants.isEmpty }
}

struct Participant: Hashable {
Expand Down
24 changes: 12 additions & 12 deletions Calendr/Previews/EventDetailsPreview.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,18 @@ private extension Strings {
private extension Array where Element == Participant {

static let mock: Self = [
.init(name: "Liam", status: .declined, isOrganizer: false, isCurrentUser: false),
.init(name: "Olivia", status: .pending, isOrganizer: false, isCurrentUser: false),
.init(name: "Noah", status: .pending, isOrganizer: false, isCurrentUser: false),
.init(name: "Emma", status: .accepted, isOrganizer: true, isCurrentUser: false),
.init(name: "Carlos", status: .maybe, isOrganizer: false, isCurrentUser: true),
.init(name: "Charlotte", status: .accepted, isOrganizer: false, isCurrentUser: false),
.init(name: "Elijah", status: .accepted, isOrganizer: false, isCurrentUser: false),
.init(name: "Nelson", status: .declined, isOrganizer: false, isCurrentUser: false),
.init(name: "Brian", status: .accepted, isOrganizer: false, isCurrentUser: false),
.init(name: "Oliver", status: .accepted, isOrganizer: false, isCurrentUser: false),
.init(name: "Lucas", status: .accepted, isOrganizer: false, isCurrentUser: false),
.init(name: "Jean", status: .maybe, isOrganizer: false, isCurrentUser: false)
.make(name: "Liam", status: .declined),
.make(name: "Olivia", status: .pending),
.make(name: "Noah", status: .pending),
.make(name: "Emma", status: .accepted, isOrganizer: true),
.make(name: "Carlos", status: .maybe, isCurrentUser: true),
.make(name: "Charlotte", status: .accepted),
.make(name: "Elijah", status: .accepted),
.make(name: "Nelson", status: .declined),
.make(name: "Brian", status: .accepted),
.make(name: "Oliver", status: .accepted),
.make(name: "Lucas", status: .accepted),
.make(name: "Jean", status: .maybe)
]
}

Expand Down
6 changes: 4 additions & 2 deletions Calendr/Providers/CalendarServiceProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@ private extension EventModel {
isAllDay: event.shouldBeAllDay,
type: .init(from: event),
calendar: .init(from: event.calendar),
participants: .init(from: event)
participants: .init(from: event),
timeZone: event.timeZone
)
}

Expand All @@ -337,7 +338,8 @@ private extension EventModel {
isAllDay: reminder.dueDateComponents!.hour == nil,
type: .reminder,
calendar: .init(from: reminder.calendar),
participants: []
participants: [],
timeZone: reminder.timeZone
)
}
}
Expand Down
10 changes: 5 additions & 5 deletions CalendrTests/EventDetailsViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ class EventDetailsViewModelTests: XCTestCase {
let viewModel = mock(
event: .make(
participants: [
.init(name: "c", status: .unknown, isOrganizer: false, isCurrentUser: false),
.init(name: "b", status: .unknown, isOrganizer: false, isCurrentUser: false),
.init(name: "me", status: .unknown, isOrganizer: false, isCurrentUser: true),
.init(name: "organizer", status: .unknown, isOrganizer: true, isCurrentUser: false),
.init(name: "a", status: .unknown, isOrganizer: false, isCurrentUser: false),
.make(name: "c"),
.make(name: "b"),
.make(name: "me", isCurrentUser: true),
.make(name: "organizer", isOrganizer: true),
.make(name: "a"),
]
)
)
Expand Down
27 changes: 27 additions & 0 deletions CalendrTests/EventViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,33 @@ class EventViewModelTests: XCTestCase {
XCTAssertEqual(viewModel.duration, "Jan 1 - Feb 2")
}

func testDuration_isSameDay_withDifferentTimeZone() {

let viewModel = mock(
event: .make(
start: .make(year: 2021, month: 1, day: 1, hour: 15),
end: .make(year: 2021, month: 1, day: 1, hour: 16),
timeZone: .init(abbreviation: "GMT-3")
)
)

XCTAssertEqual(viewModel.duration, "12:00 - 1:00 PM (GMT-3)")
}

func testDuration_isSameDay_isMeeting_withDifferentTimeZone() {

let viewModel = mock(
event: .make(
start: .make(year: 2021, month: 1, day: 1, hour: 15),
end: .make(year: 2021, month: 1, day: 1, hour: 16),
participants: [.make()],
timeZone: .init(abbreviation: "GMT-3")
)
)

XCTAssertEqual(viewModel.duration, "3:00 - 4:00 PM")
}

func testBarStyle() {

XCTAssertEqual(mock(type: .birthday).barStyle, .filled)
Expand Down

0 comments on commit 1775e5b

Please sign in to comment.