mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
180 lines
9.0 KiB
Swift
180 lines
9.0 KiB
Swift
import Foundation
|
|
import TelegramPresentationData
|
|
import TelegramStringFormatting
|
|
|
|
private let telegramReleaseDate = Date(timeIntervalSince1970: 1376438400.0)
|
|
|
|
func suggestDates(for string: String, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat) -> [(minDate: Date?, maxDate: Date, string: String?)] {
|
|
let string = string.folding(options: .diacriticInsensitive, locale: .current).trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
|
|
if string.count < 3 {
|
|
return []
|
|
}
|
|
|
|
let months: [Int: (String, String)] = [
|
|
1: (strings.Month_GenJanuary, strings.Month_ShortJanuary),
|
|
2: (strings.Month_GenFebruary, strings.Month_ShortFebruary),
|
|
3: (strings.Month_GenMarch, strings.Month_ShortMarch),
|
|
4: (strings.Month_GenApril, strings.Month_ShortApril),
|
|
5: (strings.Month_GenMay, strings.Month_ShortMay),
|
|
6: (strings.Month_GenJune, strings.Month_ShortJune),
|
|
7: (strings.Month_GenJuly, strings.Month_ShortJuly),
|
|
8: (strings.Month_GenAugust, strings.Month_ShortAugust),
|
|
9: (strings.Month_GenSeptember, strings.Month_ShortSeptember),
|
|
10: (strings.Month_GenOctober, strings.Month_ShortOctober),
|
|
11: (strings.Month_GenNovember, strings.Month_ShortNovember),
|
|
12: (strings.Month_GenDecember, strings.Month_ShortDecember)
|
|
]
|
|
|
|
let weekDays: [Int: (String, String)] = [
|
|
1: (strings.Weekday_Monday, strings.Weekday_ShortMonday),
|
|
2: (strings.Weekday_Tuesday, strings.Weekday_ShortTuesday),
|
|
3: (strings.Weekday_Wednesday, strings.Weekday_ShortWednesday),
|
|
4: (strings.Weekday_Thursday, strings.Weekday_ShortThursday),
|
|
5: (strings.Weekday_Friday, strings.Weekday_ShortFriday),
|
|
6: (strings.Weekday_Saturday, strings.Weekday_ShortSaturday),
|
|
7: (strings.Weekday_Sunday, strings.Weekday_ShortSunday.lowercased()),
|
|
]
|
|
|
|
let today = strings.Weekday_Today
|
|
let yesterday = strings.Weekday_Yesterday
|
|
let dateSeparator = dateTimeFormat.dateSeparator
|
|
|
|
var result: [(Date?, Date, String?)] = []
|
|
|
|
let calendar = Calendar.current
|
|
func getLowerDate(for date: Date) -> Date {
|
|
let components = calendar.dateComponents(in: .current, from: date)
|
|
let upperComponents = DateComponents(year: components.year, month: components.month, day: components.day, hour: 0, minute: 0, second: 0)
|
|
return calendar.date(from: upperComponents)!
|
|
}
|
|
func getUpperDate(for date: Date) -> Date {
|
|
let components = calendar.dateComponents(in: .current, from: date)
|
|
let upperComponents = DateComponents(year: components.year, month: components.month, day: components.day, hour: 23, minute: 59, second: 59)
|
|
return calendar.date(from: upperComponents)!
|
|
}
|
|
|
|
let now = Date()
|
|
let nowComponents = calendar.dateComponents(in: .current, from: now)
|
|
guard let year = nowComponents.year else {
|
|
return []
|
|
}
|
|
|
|
let midnightDate = calendar.startOfDay(for: now)
|
|
if today.lowercased().hasPrefix(string) {
|
|
let todayDate = getUpperDate(for: midnightDate)
|
|
result.append((midnightDate, todayDate, today))
|
|
}
|
|
if yesterday.lowercased().hasPrefix(string) {
|
|
let yesterdayMidnight = calendar.date(byAdding: .day, value: -1, to: midnightDate)!
|
|
let yesterdayDate = getUpperDate(for: yesterdayMidnight)
|
|
result.append((yesterdayMidnight, yesterdayDate, yesterday))
|
|
}
|
|
|
|
func getLowerMonthDate(month: Int, year: Int) -> Date {
|
|
let monthComponents = DateComponents(year: year, month: month)
|
|
let date = calendar.date(from: monthComponents)!
|
|
let range = calendar.range(of: .day, in: .month, for: date)!
|
|
let upperComponents = DateComponents(year: year, month: month, day: 1, hour: 0, minute: 0, second: 0)
|
|
return calendar.date(from: upperComponents)!
|
|
}
|
|
|
|
func getUpperMonthDate(month: Int, year: Int) -> Date {
|
|
let monthComponents = DateComponents(year: year, month: month)
|
|
let date = calendar.date(from: monthComponents)!
|
|
let range = calendar.range(of: .day, in: .month, for: date)!
|
|
let numDays = range.count
|
|
let upperComponents = DateComponents(year: year, month: month, day: numDays, hour: 23, minute: 59, second: 59)
|
|
return calendar.date(from: upperComponents)!
|
|
}
|
|
|
|
let decimalRange = string.rangeOfCharacter(from: .decimalDigits)
|
|
if decimalRange != nil {
|
|
if string.count == 4, let value = Int(string), value <= year {
|
|
let minDate = getLowerMonthDate(month: 1, year: value)
|
|
let maxDate = getUpperMonthDate(month: 12, year: value)
|
|
if maxDate > telegramReleaseDate {
|
|
result.append((minDate, maxDate, "\(value)"))
|
|
}
|
|
} else {
|
|
do {
|
|
func process(_ date: Date) {
|
|
var resultDate = date
|
|
if resultDate > now && !calendar.isDate(resultDate, equalTo: now, toGranularity: .year) {
|
|
if let date = calendar.date(byAdding: .year, value: -1, to: resultDate) {
|
|
resultDate = date
|
|
}
|
|
}
|
|
|
|
let stringComponents = string.components(separatedBy: dateSeparator)
|
|
if stringComponents.count < 3 {
|
|
for i in 0..<5 {
|
|
if let date = calendar.date(byAdding: .year, value: -i, to: resultDate) {
|
|
result.append((nil, date, nil))
|
|
}
|
|
}
|
|
} else if resultDate < now {
|
|
result.append((nil, resultDate, nil))
|
|
}
|
|
}
|
|
let dd = try NSDataDetector(types: NSTextCheckingResult.CheckingType.date.rawValue)
|
|
if let match = dd.firstMatch(in: string, options: [], range: NSMakeRange(0, string.utf16.count)), let date = match.date, date > telegramReleaseDate {
|
|
process(date)
|
|
} else if let match = dd.firstMatch(in: string.replacingOccurrences(of: ".", with: "/"), options: [], range: NSMakeRange(0, string.utf16.count)), let date = match.date, date > telegramReleaseDate {
|
|
process(date)
|
|
}
|
|
} catch {
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
for (day, value) in weekDays {
|
|
let dayName = value.0.lowercased()
|
|
let shortDayName = value.1.lowercased()
|
|
if string == shortDayName || (string.count >= shortDayName.count && dayName.hasPrefix(string)) {
|
|
var nextDateComponent = calendar.dateComponents([.hour, .minute, .second], from: now)
|
|
nextDateComponent.weekday = day + calendar.firstWeekday
|
|
if let date = calendar.nextDate(after: now, matching: nextDateComponent, matchingPolicy: .nextTime, direction: .backward) {
|
|
let lowerAnchorDate = getLowerDate(for: date)
|
|
let upperAnchorDate = getUpperDate(for: date)
|
|
for i in 0..<5 {
|
|
if let lowerDate = calendar.date(byAdding: .hour, value: -24 * 7 * i, to: lowerAnchorDate), let upperDate = calendar.date(byAdding: .hour, value: -24 * 7 * i, to: upperAnchorDate) {
|
|
if calendar.isDate(upperDate, equalTo: now, toGranularity: .weekOfYear) {
|
|
result.append((lowerDate, upperDate, value.0))
|
|
} else {
|
|
result.append((lowerDate, upperDate, nil))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let cleanString = string.trimmingCharacters(in: .decimalDigits).trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let cleanDigits = string.trimmingCharacters(in: .letters).trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
|
for (month, value) in months {
|
|
let monthName = value.0.lowercased()
|
|
let shortMonthName = value.1.lowercased()
|
|
if cleanString == shortMonthName || (cleanString.count >= shortMonthName.count && monthName.hasPrefix(cleanString)) {
|
|
if cleanDigits.count == 4, let year = Int(cleanDigits) {
|
|
let lowerDate = getLowerMonthDate(month: month, year: year)
|
|
let upperDate = getUpperMonthDate(month: month, year: year)
|
|
if upperDate <= now && upperDate > telegramReleaseDate {
|
|
result.append((lowerDate, upperDate, stringForMonth(strings: strings, month: Int32(month - 1), ofYear: Int32(year - 1900))))
|
|
}
|
|
} else if cleanDigits.isEmpty {
|
|
for i in (year - 7 ... year).reversed() {
|
|
let lowerDate = getUpperMonthDate(month: month, year: i)
|
|
let upperDate = getUpperMonthDate(month: month, year: i)
|
|
if upperDate <= now && upperDate > telegramReleaseDate {
|
|
result.append((lowerDate, upperDate, stringForMonth(strings: strings, month: Int32(month - 1), ofYear: Int32(i - 1900))))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|