Skip to content

Commit ad715e5

Browse files
authored
Merge pull request #8282 from woocommerce/issue/8146-introduce-last-range-options
[Analytics Hub] Enforce internal timezone usage for time ranges descriptions
2 parents 86f10d1 + 3c8d7f8 commit ad715e5

File tree

10 files changed

+119
-64
lines changed

10 files changed

+119
-64
lines changed

Networking/Networking/Extensions/DateFormatter+Woo.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,31 +107,31 @@ public extension DateFormatter {
107107
/// Date formatter used for creating the properly-formatted date range info. Typically
108108
/// used when setting the end date on `AnalyticsHubTimeRangeGenerator`.
109109
///
110-
public static let analyticsHubDayMonthYearFormatter: DateFormatter = {
110+
public static func createAnalyticsHubDayMonthYearFormatter(timezone: TimeZone) -> DateFormatter {
111111
let formatter = DateFormatter()
112-
formatter.locale = Locale(identifier: "en_US_POSIX")
112+
formatter.timeZone = timezone
113113
formatter.dateFormat = "MMM d, yyyy"
114114
return formatter
115-
}()
115+
}
116116

117117
/// Date formatter used for creating the properly-formatted date range info. Typically
118118
/// used when setting the end date of a same-month range on `AnalyticsHubTimeRangeGenerator`.
119119
///
120-
public static let analyticsHubDayYearFormatter: DateFormatter = {
120+
public static func createAnalyticsHubDayYearFormatter(timezone: TimeZone) -> DateFormatter {
121121
let formatter = DateFormatter()
122-
formatter.locale = Locale(identifier: "en_US_POSIX")
122+
formatter.timeZone = timezone
123123
formatter.dateFormat = "d, yyyy"
124124
return formatter
125-
}()
125+
}
126126

127127
/// Date formatter used for creating the properly-formatted date range info. Typically
128128
/// used when setting the start date on `AnalyticsHubTimeRangeGenerator`.
129129
///
130-
public static let analyticsHubDayMonthFormatter: DateFormatter = {
130+
public static func createAnalyticsHubDayMonthFormatter(timezone: TimeZone) -> DateFormatter {
131131
let formatter = DateFormatter()
132-
formatter.locale = Locale(identifier: "en_US_POSIX")
132+
formatter.timeZone = timezone
133133
formatter.dateFormat = "MMM d"
134134
return formatter
135-
}()
135+
}
136136
}
137137
}

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/Time Range/AnalyticsHubTimeRange.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@ struct AnalyticsHubTimeRange {
44
let start: Date
55
let end: Date
66

7-
func formatToString(simplified: Bool, calendar: Calendar) -> String {
7+
func formatToString(simplified: Bool, timezone: TimeZone, calendar: Calendar) -> String {
88
if simplified {
9-
return DateFormatter.Stats.analyticsHubDayMonthYearFormatter.string(from: start)
9+
return DateFormatter.Stats.createAnalyticsHubDayMonthYearFormatter(timezone: timezone).string(from: start)
1010
}
1111

12-
let startDateDescription = DateFormatter.Stats.analyticsHubDayMonthFormatter.string(from: start)
12+
let startDateDescription = DateFormatter.Stats.createAnalyticsHubDayMonthFormatter(timezone: timezone).string(from: start)
1313

14+
let endDateDescription: String
1415
if start.isSameMonth(as: end, using: calendar) {
15-
return "\(startDateDescription) - \(DateFormatter.Stats.analyticsHubDayYearFormatter.string(from: end))"
16+
endDateDescription = DateFormatter.Stats.createAnalyticsHubDayYearFormatter(timezone: timezone).string(from: end)
1617
} else {
17-
return "\(startDateDescription) - \(DateFormatter.Stats.analyticsHubDayMonthYearFormatter.string(from: end))"
18+
endDateDescription = DateFormatter.Stats.createAnalyticsHubDayMonthYearFormatter(timezone: timezone).string(from: end)
1819
}
20+
return "\(startDateDescription) - \(endDateDescription)"
1921
}
2022
}

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/Time Range/AnalyticsHubTimeRangeSelection.swift

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ public class AnalyticsHubTimeRangeSelection {
1010
private let formattedCurrentRangeText: String?
1111
private let formattedPreviousRangeText: String?
1212
let rangeSelectionDescription: String
13-
1413
/// Provide a date description of the current time range set internally.
1514
/// - Returns the Time range in a UI friendly format. If the current time range is not available,
1615
/// then returns an presentable error message.
@@ -20,7 +19,6 @@ public class AnalyticsHubTimeRangeSelection {
2019
}
2120
return currentTimeRangeDescription
2221
}
23-
2422
/// Generates a date description of the previous time range set internally.
2523
/// - Returns the Time range in a UI friendly format. If the previous time range is not available,
2624
/// then returns an presentable error message.
@@ -56,9 +54,11 @@ public class AnalyticsHubTimeRangeSelection {
5654

5755
let simplifiedDescription = selectionType == .today
5856
self.formattedCurrentRangeText = currentTimeRange?.formatToString(simplified: simplifiedDescription,
59-
calendar: calendar)
57+
timezone: timezone,
58+
calendar: calendar)
6059
self.formattedPreviousRangeText = previousTimeRange?.formatToString(simplified: simplifiedDescription,
61-
calendar: calendar)
60+
timezone: timezone,
61+
calendar: calendar)
6262
self.rangeSelectionDescription = selectionType.description
6363
}
6464

@@ -71,7 +71,6 @@ public class AnalyticsHubTimeRangeSelection {
7171
}
7272
return currentTimeRange
7373
}
74-
7574
/// Unwrap the generated previous `AnalyticsHubTimeRange`relative to the selected one
7675
/// based on the `selectedTimeRange` provided during initialization.
7776
/// - throws a `.previousRangeGenerationFailed` error if the unwrap fails.
@@ -118,10 +117,8 @@ extension AnalyticsHubTimeRangeSelection {
118117
}
119118
}
120119
}
121-
122120
// MARK: - Constants
123121
extension AnalyticsHubTimeRangeSelection {
124-
125122
enum TimeRangeGeneratorError: Error {
126123
case selectedRangeGenerationFailed
127124
case previousRangeGenerationFailed

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7465,17 +7465,25 @@
74657465
path = CustomerNoteSection;
74667466
sourceTree = "<group>";
74677467
};
7468-
B6F379662937831D00718561 /* Time Range */ = {
7468+
B66D6CEF293A4D990075D4AF /* Range Data Generation */ = {
74697469
isa = PBXGroup;
74707470
children = (
7471-
B6440FB5292E72DA0012D506 /* AnalyticsHubTimeRangeSelection.swift */,
7472-
B6F379672937836700718561 /* AnalyticsHubTimeRange.swift */,
74737471
B6F3796929378B3900718561 /* AnalyticsHubMonthRangeData.swift */,
74747472
B6F3796B293794A000718561 /* AnalyticsHubYearRangeData.swift */,
74757473
B6F3796D293796BC00718561 /* AnalyticsHubWeekRangeData.swift */,
74767474
B6F3796F293798ED00718561 /* AnalyticsHubDayRangeData.swift */,
74777475
B66D6CEB29396A3E0075D4AF /* AnalyticsHubTimeRangeData.swift */,
74787476
);
7477+
path = "Range Data Generation";
7478+
sourceTree = "<group>";
7479+
};
7480+
B6F379662937831D00718561 /* Time Range */ = {
7481+
isa = PBXGroup;
7482+
children = (
7483+
B66D6CEF293A4D990075D4AF /* Range Data Generation */,
7484+
B6440FB5292E72DA0012D506 /* AnalyticsHubTimeRangeSelection.swift */,
7485+
B6F379672937836700718561 /* AnalyticsHubTimeRange.swift */,
7486+
);
74797487
path = "Time Range";
74807488
sourceTree = "<group>";
74817489
};

WooCommerce/WooCommerceTests/ViewRelated/Dashboard/Analytics Hub/AnalyticsHubTimeRangeSelectionTests.swift

Lines changed: 88 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,84 +2,103 @@ import XCTest
22
@testable import WooCommerce
33

44
final class AnalyticsHubTimeRangeSelectionTests: XCTestCase {
5-
private var dateFormatter: DateFormatter = {
6-
let dateFormatter = DateFormatter()
7-
dateFormatter.dateFormat = "yyyy-MM-dd"
8-
return dateFormatter
5+
private var testTimezone: TimeZone = {
6+
TimeZone(abbreviation: "UTC") ?? TimeZone.current
7+
}()
8+
9+
private var testCalendar: Calendar = {
10+
var calendar = Calendar(identifier: .iso8601)
11+
calendar.timeZone = TimeZone(abbreviation: "UTC") ?? TimeZone.current
12+
return calendar
913
}()
1014

1115
func test_when_time_range_inits_with_yearToDate_then_generate_expected_ranges() throws {
1216
// Given
13-
let currentDate = dateFrom("2020-02-29")
14-
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .yearToDate, currentDate: currentDate)
17+
let today = currentDate(from: "2020-02-29")
18+
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .yearToDate,
19+
currentDate: today,
20+
timezone: testTimezone,
21+
calendar: testCalendar)
1522

1623
// When
1724
let currentTimeRange = try timeRange.unwrapCurrentTimeRange()
1825
let previousTimeRange = try timeRange.unwrapPreviousTimeRange()
1926

2027
// Then
21-
XCTAssertEqual(currentTimeRange.start, dateFrom("2020-01-01"))
22-
XCTAssertEqual(currentTimeRange.end, dateFrom("2020-02-29"))
28+
XCTAssertEqual(currentTimeRange.start, startDate(from: "2020-01-01"))
29+
XCTAssertEqual(currentTimeRange.end, currentDate(from: "2020-02-29"))
2330

24-
XCTAssertEqual(previousTimeRange.start, dateFrom("2019-01-01"))
25-
XCTAssertEqual(previousTimeRange.end, dateFrom("2019-02-28"))
31+
XCTAssertEqual(previousTimeRange.start, startDate(from: "2019-01-01"))
32+
XCTAssertEqual(previousTimeRange.end, currentDate(from: "2019-02-28"))
2633
}
2734

2835
func test_when_time_range_inits_with_monthToDate_then_generate_expected_ranges() throws {
2936
// Given
30-
let currentDate = dateFrom("2010-07-31")
31-
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .monthToDate, currentDate: currentDate)
37+
let today = currentDate(from: "2010-07-31")
38+
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .monthToDate,
39+
currentDate: today,
40+
timezone: testTimezone,
41+
calendar: testCalendar)
3242

3343
// When
3444
let currentTimeRange = try timeRange.unwrapCurrentTimeRange()
3545
let previousTimeRange = try timeRange.unwrapPreviousTimeRange()
3646

3747
// Then
38-
XCTAssertEqual(currentTimeRange.start, dateFrom("2010-07-01"))
39-
XCTAssertEqual(currentTimeRange.end, dateFrom("2010-07-31"))
48+
XCTAssertEqual(currentTimeRange.start, startDate(from: "2010-07-01"))
49+
XCTAssertEqual(currentTimeRange.end, currentDate(from: "2010-07-31"))
4050

41-
XCTAssertEqual(previousTimeRange.start, dateFrom("2010-06-01"))
42-
XCTAssertEqual(previousTimeRange.end, dateFrom("2010-06-30"))
51+
XCTAssertEqual(previousTimeRange.start, startDate(from: "2010-06-01"))
52+
XCTAssertEqual(previousTimeRange.end, currentDate(from: "2010-06-30"))
4353
}
4454

4555
func test_when_time_range_inits_with_weekToDate_then_generate_expected_ranges() throws {
4656
// Given
47-
let currentDate = dateFrom("2022-07-01")
48-
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .weekToDate, currentDate: currentDate)
57+
let today = currentDate(from: "2022-07-01")
58+
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .weekToDate,
59+
currentDate: today,
60+
timezone: testTimezone,
61+
calendar: testCalendar)
4962

5063
// When
5164
let currentTimeRange = try timeRange.unwrapCurrentTimeRange()
5265
let previousTimeRange = try timeRange.unwrapPreviousTimeRange()
5366

5467
// Then
55-
XCTAssertEqual(currentTimeRange.start, dateFrom("2022-06-27"))
56-
XCTAssertEqual(currentTimeRange.end, dateFrom("2022-07-01"))
68+
XCTAssertEqual(currentTimeRange.start, startDate(from: "2022-06-27"))
69+
XCTAssertEqual(currentTimeRange.end, currentDate(from: "2022-07-01"))
5770

58-
XCTAssertEqual(previousTimeRange.start, dateFrom("2022-06-20"))
59-
XCTAssertEqual(previousTimeRange.end, dateFrom("2022-06-24"))
71+
XCTAssertEqual(previousTimeRange.start, startDate(from: "2022-06-20"))
72+
XCTAssertEqual(previousTimeRange.end, currentDate(from: "2022-06-24"))
6073
}
6174

6275
func test_when_time_range_inits_with_today_then_generate_expected_ranges() throws {
6376
// Given
64-
let currentDate = dateFrom("2022-07-01")
65-
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .today, currentDate: currentDate)
77+
let today = currentDate(from: "2022-07-01")
78+
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .today,
79+
currentDate: today,
80+
timezone: testTimezone,
81+
calendar: testCalendar)
6682

6783
// When
6884
let currentTimeRange = try timeRange.unwrapCurrentTimeRange()
6985
let previousTimeRange = try timeRange.unwrapPreviousTimeRange()
7086

7187
// Then
72-
XCTAssertEqual(currentTimeRange.start, dateFrom("2022-07-01"))
73-
XCTAssertEqual(currentTimeRange.end, dateFrom("2022-07-01"))
88+
XCTAssertEqual(currentTimeRange.start, startDate(from: "2022-07-01"))
89+
XCTAssertEqual(currentTimeRange.end, currentDate(from: "2022-07-01"))
7490

75-
XCTAssertEqual(previousTimeRange.start, dateFrom("2022-06-30"))
76-
XCTAssertEqual(previousTimeRange.end, dateFrom("2022-06-30"))
91+
XCTAssertEqual(previousTimeRange.start, startDate(from: "2022-06-30"))
92+
XCTAssertEqual(previousTimeRange.end, currentDate(from: "2022-06-30"))
7793
}
7894

7995
func test_when_time_range_inits_with_yearToDate_then_generate_expected_descriptions() throws {
8096
// Given
81-
let currentDate = dateFrom("2022-07-01")
82-
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .yearToDate, currentDate: currentDate)
97+
let today = currentDate(from: "2022-07-01")
98+
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .yearToDate,
99+
currentDate: today,
100+
timezone: testTimezone,
101+
calendar: testCalendar)
83102

84103
// When
85104
let currentRangeDescription = timeRange.currentRangeDescription
@@ -92,8 +111,11 @@ final class AnalyticsHubTimeRangeSelectionTests: XCTestCase {
92111

93112
func test_when_time_range_inits_with_monthToDate_then_generate_expected_descriptions() throws {
94113
// Given
95-
let currentDate = dateFrom("2022-07-31")
96-
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .monthToDate, currentDate: currentDate)
114+
let today = currentDate(from: "2022-07-31")
115+
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .monthToDate,
116+
currentDate: today,
117+
timezone: testTimezone,
118+
calendar: testCalendar)
97119

98120
// When
99121
let currentRangeDescription = timeRange.currentRangeDescription
@@ -106,8 +128,11 @@ final class AnalyticsHubTimeRangeSelectionTests: XCTestCase {
106128

107129
func test_when_time_range_inits_with_weekToDate_then_generate_expected_descriptions() throws {
108130
// Given
109-
let currentDate = dateFrom("2022-07-29")
110-
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .weekToDate, currentDate: currentDate)
131+
let today = currentDate(from: "2022-07-29")
132+
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .weekToDate,
133+
currentDate: today,
134+
timezone: testTimezone,
135+
calendar: testCalendar)
111136

112137
// When
113138
let currentRangeDescription = timeRange.currentRangeDescription
@@ -120,8 +145,11 @@ final class AnalyticsHubTimeRangeSelectionTests: XCTestCase {
120145

121146
func test_when_time_range_inits_with_weekToDate_with_different_months_then_generate_expected_descriptions() throws {
122147
// Given
123-
let currentDate = dateFrom("2022-07-02")
124-
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .weekToDate, currentDate: currentDate)
148+
let today = currentDate(from: "2022-07-02")
149+
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .weekToDate,
150+
currentDate: today,
151+
timezone: testTimezone,
152+
calendar: testCalendar)
125153

126154
// When
127155
let currentRangeDescription = timeRange.currentRangeDescription
@@ -134,8 +162,11 @@ final class AnalyticsHubTimeRangeSelectionTests: XCTestCase {
134162

135163
func test_when_time_range_inits_with_today_then_generate_expected_descriptions() throws {
136164
// Given
137-
let currentDate = dateFrom("2022-07-01")
138-
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .today, currentDate: currentDate)
165+
let today = currentDate(from: "2022-07-01")
166+
let timeRange = AnalyticsHubTimeRangeSelection(selectionType: .today,
167+
currentDate: today,
168+
timezone: testTimezone,
169+
calendar: testCalendar)
139170

140171
// When
141172
let currentRangeDescription = timeRange.currentRangeDescription
@@ -146,7 +177,24 @@ final class AnalyticsHubTimeRangeSelectionTests: XCTestCase {
146177
XCTAssertEqual(previousRangeDescription, "Jun 30, 2022")
147178
}
148179

149-
private func dateFrom(_ date: String) -> Date {
150-
return dateFormatter.date(from: date)!
180+
private func currentDate(from date: String) -> Date {
181+
let dateFormatter = DateFormatter()
182+
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
183+
dateFormatter.timeZone = testTimezone
184+
return dateFormatter.date(from: date + "T11:30:00+0000")!
185+
}
186+
187+
private func startDate(from date: String) -> Date? {
188+
let dateFormatter = DateFormatter()
189+
dateFormatter.dateFormat = "yyyy-MM-dd"
190+
dateFormatter.timeZone = testTimezone
191+
return dateFormatter.date(from: date)?.startOfDay(timezone: testTimezone)
192+
}
193+
194+
private func endDate(from date: String) -> Date? {
195+
let dateFormatter = DateFormatter()
196+
dateFormatter.dateFormat = "yyyy-MM-dd"
197+
dateFormatter.timeZone = testTimezone
198+
return dateFormatter.date(from: date)?.endOfDay(timezone: testTimezone)
151199
}
152200
}

0 commit comments

Comments
 (0)