Widget Features: - Add inline voting to timeline widget when no entry exists for today - Show random prompt from notification strings in voting mode - Update vote widget to use simple icon style for selection - Make stats bar full width in voted state view - Add Localizable.strings to widget extension target Bug Fixes: - Fix inverted date calculation in InsightsViewModel streak logic - Replace force unwraps with safe optional handling in widgets - Replace fatalError calls with graceful error handling - Fix CSV import safety in SettingsView Warning Fixes: - Add @retroactive to Color and Date extension conformances - Update deprecated onChange(of:perform:) to new syntax - Replace deprecated applicationIconBadgeNumber with setBadgeCount - Replace deprecated UIApplication.shared.windows API - Add @preconcurrency for Swift 6 protocol conformances - Add missing widget family cases to switch statement - Remove unused variables and #warning directives 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
104 lines
3.3 KiB
Swift
104 lines
3.3 KiB
Swift
//
|
|
// Date+Extensions.swift
|
|
// Feels (iOS)
|
|
//
|
|
// Created by Trey Tartt on 2/19/22.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
extension Date: @retroactive RawRepresentable {
|
|
public var rawValue: String {
|
|
self.timeIntervalSinceReferenceDate.description
|
|
}
|
|
|
|
public init?(rawValue: String) {
|
|
self = Date(timeIntervalSinceReferenceDate: Double(rawValue) ?? 0.0)
|
|
}
|
|
|
|
var startOfDay: Date {
|
|
return Calendar.current.startOfDay(for: self)
|
|
}
|
|
|
|
var startOfMonth: Date {
|
|
|
|
let calendar = Calendar(identifier: .gregorian)
|
|
let components = calendar.dateComponents([.year, .month], from: self)
|
|
|
|
return calendar.date(from: components)!
|
|
}
|
|
|
|
var endOfDay: Date {
|
|
var components = DateComponents()
|
|
components.day = 1
|
|
components.second = -1
|
|
return Calendar.current.date(byAdding: components, to: startOfDay)!
|
|
}
|
|
|
|
var endOfMonth: Date {
|
|
var components = DateComponents()
|
|
components.month = 1
|
|
components.second = -1
|
|
return Calendar(identifier: .gregorian).date(byAdding: components, to: startOfMonth)!
|
|
}
|
|
|
|
func toLocalTime() -> Date {
|
|
let timezone = TimeZone.current
|
|
let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
|
|
return Date(timeInterval: seconds, since: self)
|
|
}
|
|
|
|
var weekday: Int {
|
|
Calendar.current.component(.weekday, from: self)
|
|
}
|
|
|
|
var firstDayOfTheMonth: Date {
|
|
Calendar.current.dateComponents([.calendar, .year,.month], from: self).date!
|
|
}
|
|
|
|
static public func dates(from fromDate: Date, toDate: Date, includingToDate: Bool = false) -> [Date] {
|
|
var dates: [Date] = []
|
|
var date = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: fromDate)!
|
|
let toDate = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: toDate)!
|
|
|
|
if includingToDate {
|
|
while date <= toDate {
|
|
dates.append(date)
|
|
guard let newDate = Calendar.current.date(byAdding: .day, value: 1, to: date) else { break }
|
|
date = newDate
|
|
}
|
|
} else {
|
|
while date < toDate {
|
|
dates.append(date)
|
|
guard let newDate = Calendar.current.date(byAdding: .day, value: 1, to: date) else { break }
|
|
date = newDate
|
|
}
|
|
}
|
|
|
|
return dates
|
|
}
|
|
|
|
static func dateRange(monthInt: Int, yearInt: Int) -> (startDate: Date, endDate: Date) {
|
|
var dateComponents = DateComponents()
|
|
dateComponents.year = yearInt
|
|
dateComponents.month = monthInt
|
|
dateComponents.day = 3
|
|
dateComponents.hour = 12
|
|
var userCalendar = Calendar(identifier: .gregorian)
|
|
userCalendar.timeZone = TimeZone(secondsFromGMT: 0)!
|
|
let someDateTime = userCalendar.date(from: dateComponents)!
|
|
|
|
let startDate = someDateTime.startOfMonth
|
|
var endDate = someDateTime.endOfMonth
|
|
endDate = Calendar.current.date(byAdding: .hour, value: -8, to: endDate)!
|
|
|
|
return (startDate, endDate)
|
|
}
|
|
|
|
func formattedDate() -> String {
|
|
let dateFormatter = DateFormatter()
|
|
dateFormatter.dateFormat = "MMM dd, yyyy"
|
|
return dateFormatter.string(from: self)
|
|
}
|
|
}
|