import XCTest @testable import PortfolioJournal final class DateExtensionsTests: XCTestCase { // MARK: - Start of Day func testStartOfDay_returnsDateAtMidnight() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 components.hour = 14 components.minute = 30 let date = Calendar.current.date(from: components)! // When let result = date.startOfDay // Then let resultComponents = Calendar.current.dateComponents([.hour, .minute, .second], from: result) XCTAssertEqual(resultComponents.hour, 0) XCTAssertEqual(resultComponents.minute, 0) XCTAssertEqual(resultComponents.second, 0) } // MARK: - Start of Month func testStartOfMonth_returnsFirstDayOfMonth() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 let date = Calendar.current.date(from: components)! // When let result = date.startOfMonth // Then let resultComponents = Calendar.current.dateComponents([.day, .month, .year], from: result) XCTAssertEqual(resultComponents.day, 1) XCTAssertEqual(resultComponents.month, 6) XCTAssertEqual(resultComponents.year, 2024) } // MARK: - Start of Year func testStartOfYear_returnsJanuaryFirst() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 let date = Calendar.current.date(from: components)! // When let result = date.startOfYear // Then let resultComponents = Calendar.current.dateComponents([.day, .month, .year], from: result) XCTAssertEqual(resultComponents.day, 1) XCTAssertEqual(resultComponents.month, 1) XCTAssertEqual(resultComponents.year, 2024) } // MARK: - End of Month func testEndOfMonth_returnsLastDayOfMonth() { // Given: June has 30 days var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 let date = Calendar.current.date(from: components)! // When let result = date.endOfMonth // Then let resultComponents = Calendar.current.dateComponents([.day, .month], from: result) XCTAssertEqual(resultComponents.day, 30) XCTAssertEqual(resultComponents.month, 6) } func testEndOfMonth_handlesFebruaryInLeapYear() { // Given: February 2024 (leap year) has 29 days var components = DateComponents() components.year = 2024 components.month = 2 components.day = 10 let date = Calendar.current.date(from: components)! // When let result = date.endOfMonth // Then let resultComponents = Calendar.current.dateComponents([.day, .month], from: result) XCTAssertEqual(resultComponents.day, 29) XCTAssertEqual(resultComponents.month, 2) } // MARK: - Same Day Comparison func testIsSameDay_withSameDay_returnsTrue() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 components.hour = 10 let date1 = Calendar.current.date(from: components)! components.hour = 20 let date2 = Calendar.current.date(from: components)! // When/Then XCTAssertTrue(date1.isSameDay(as: date2)) } func testIsSameDay_withDifferentDays_returnsFalse() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 let date1 = Calendar.current.date(from: components)! components.day = 16 let date2 = Calendar.current.date(from: components)! // When/Then XCTAssertFalse(date1.isSameDay(as: date2)) } // MARK: - Same Month Comparison func testIsSameMonth_withSameMonth_returnsTrue() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 1 let date1 = Calendar.current.date(from: components)! components.day = 30 let date2 = Calendar.current.date(from: components)! // When/Then XCTAssertTrue(date1.isSameMonth(as: date2)) } func testIsSameMonth_withDifferentMonths_returnsFalse() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 let date1 = Calendar.current.date(from: components)! components.month = 7 let date2 = Calendar.current.date(from: components)! // When/Then XCTAssertFalse(date1.isSameMonth(as: date2)) } // MARK: - Same Year Comparison func testIsSameYear_withSameYear_returnsTrue() { // Given var components = DateComponents() components.year = 2024 components.month = 1 let date1 = Calendar.current.date(from: components)! components.month = 12 let date2 = Calendar.current.date(from: components)! // When/Then XCTAssertTrue(date1.isSameYear(as: date2)) } func testIsSameYear_withDifferentYears_returnsFalse() { // Given var components = DateComponents() components.year = 2024 components.month = 6 let date1 = Calendar.current.date(from: components)! components.year = 2023 let date2 = Calendar.current.date(from: components)! // When/Then XCTAssertFalse(date1.isSameYear(as: date2)) } // MARK: - Adding Time func testAddingDays_addsCorrectly() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 let date = Calendar.current.date(from: components)! // When let result = date.adding(days: 10) // Then let resultComponents = Calendar.current.dateComponents([.day, .month], from: result) XCTAssertEqual(resultComponents.day, 25) } func testAddingDays_handlesNegativeValues() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 let date = Calendar.current.date(from: components)! // When let result = date.adding(days: -10) // Then let resultComponents = Calendar.current.dateComponents([.day, .month], from: result) XCTAssertEqual(resultComponents.day, 5) } func testAddingMonths_addsCorrectly() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 let date = Calendar.current.date(from: components)! // When let result = date.adding(months: 3) // Then let resultComponents = Calendar.current.dateComponents([.month, .year], from: result) XCTAssertEqual(resultComponents.month, 9) XCTAssertEqual(resultComponents.year, 2024) } func testAddingYears_addsCorrectly() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 let date = Calendar.current.date(from: components)! // When let result = date.adding(years: 2) // Then let resultComponents = Calendar.current.dateComponents([.year], from: result) XCTAssertEqual(resultComponents.year, 2026) } // MARK: - Days Between func testDaysBetween_calculatesCorrectly() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 1 let startDate = Calendar.current.date(from: components)! components.day = 15 let endDate = Calendar.current.date(from: components)! // When let result = startDate.daysBetween(endDate) // Then XCTAssertEqual(result, 14) } func testDaysBetween_withReversedDates_returnsNegative() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 15 let startDate = Calendar.current.date(from: components)! components.day = 1 let endDate = Calendar.current.date(from: components)! // When let result = startDate.daysBetween(endDate) // Then XCTAssertEqual(result, -14) } // MARK: - Months Between func testMonthsBetween_calculatesCorrectly() { // Given var components = DateComponents() components.year = 2024 components.month = 1 components.day = 15 let startDate = Calendar.current.date(from: components)! components.month = 6 let endDate = Calendar.current.date(from: components)! // When let result = startDate.monthsBetween(endDate) // Then XCTAssertEqual(result, 5) } // MARK: - Years Between func testYearsBetween_calculatesCorrectly() { // Given var components = DateComponents() components.year = 2020 components.month = 1 components.day = 1 let startDate = Calendar.current.date(from: components)! components.year = 2024 let endDate = Calendar.current.date(from: components)! // When let result = startDate.yearsBetween(endDate) // Then XCTAssertEqual(result, 4.0, accuracy: 0.1) } // MARK: - DateRange Tests func testDateRange_contains_withDateInRange_returnsTrue() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 1 let start = Calendar.current.date(from: components)! components.day = 30 let end = Calendar.current.date(from: components)! let range = DateRange(start: start, end: end) components.day = 15 let testDate = Calendar.current.date(from: components)! // When/Then XCTAssertTrue(range.contains(testDate)) } func testDateRange_contains_withDateOutsideRange_returnsFalse() { // Given var components = DateComponents() components.year = 2024 components.month = 6 components.day = 1 let start = Calendar.current.date(from: components)! components.day = 30 let end = Calendar.current.date(from: components)! let range = DateRange(start: start, end: end) components.month = 7 components.day = 15 let testDate = Calendar.current.date(from: components)! // When/Then XCTAssertFalse(range.contains(testDate)) } func testDateRange_lastMonths_createsCorrectRange() { // Given/When let range = DateRange.last(months: 3) // Then let monthsDiff = range.start.monthsBetween(range.end) XCTAssertEqual(monthsDiff, 3) } }