Я пытаюсь понять, как определить, происходит ли данная временная метка сегодня или +1 / -1 дней. По сути, я бы хотел сделать что-то вроде этого (Псевдокод)
IF days_from_today(timestamp) == -1 RETURN 'Yesterday'
ELSE IF days_from_today(timestamp) == 0 RETURN 'Today'
ELSE IF days_from_today(timestamp) == 1 RETURN 'Tomorrow'
ELSE IF days_from_today(timestamp) < 1 RETURN days_from_today(timestamp) + ' days ago'
ELSE RETURN 'In ' + days_from_today(timestamp) + ' ago'
Но что важно, это должно быть в Swift, и я борюсь с объектами NSDate / NSCalendar. Я начал с расчета разницы во времени следующим образом:
let calendar = NSCalendar.currentCalendar()
let date = NSDate(timeIntervalSince1970: Double(timestamp))
let timeDifference = calendar.components([.Second,.Minute,.Day,.Hour],
fromDate: date, toDate: NSDate(), options: NSCalendarOptions())
Однако сравнивать таким способом непросто, потому что .Day
различается в зависимости от времени суток и метки времени. В PHP я бы просто использовал mktime для создания новой даты, основанной на начале дня (т.е. mktime(0,0,0)
), но я не уверен, что это самый простой способ сделать это в Swift.
Кто-нибудь знает, как к этому подойти? Может быть, лучше было бы расширить NSDate или что-то подобное?
5 ответов
Calendar
имеет методы для всех трех случаев
func isDateInYesterday(_ date: Date) -> Bool
func isDateInToday(_ date: Date) -> Bool
func isDateInTomorrow(_ date: Date) -> Bool
Чтобы рассчитать дни раньше, чем вчера, используйте
func dateComponents(_ components: Set<Calendar.Component>,
from start: Date,
to end: Date) -> DateComponents
Передать [.day]
в components
и получить свойство day
из результата.
Это функция, которая также учитывает is in
для более ранних и более поздних дат, удаляя временную часть (Swift 3+).
func dayDifference(from interval : TimeInterval) -> String
{
let calendar = Calendar.current
let date = Date(timeIntervalSince1970: interval)
if calendar.isDateInYesterday(date) { return "Yesterday" }
else if calendar.isDateInToday(date) { return "Today" }
else if calendar.isDateInTomorrow(date) { return "Tomorrow" }
else {
let startOfNow = calendar.startOfDay(for: Date())
let startOfTimeStamp = calendar.startOfDay(for: date)
let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
let day = components.day!
if day < 1 { return "\(-day) days ago" }
else { return "In \(day) days" }
}
}
В качестве альтернативы вы можете использовать DateFormatter
для вчера , сегодня и завтра , чтобы бесплатно получить локализованные строки
func dayDifference(from interval : TimeInterval) -> String
{
let calendar = Calendar.current
let date = Date(timeIntervalSince1970: interval)
let startOfNow = calendar.startOfDay(for: Date())
let startOfTimeStamp = calendar.startOfDay(for: date)
let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
let day = components.day!
if abs(day) < 2 {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .none
formatter.doesRelativeDateFormatting = true
return formatter.string(from: date)
} else if day > 1 {
return "In \(day) days"
} else {
return "\(-day) days ago"
}
}
Обновить:
В macOS 10.15 / iOS 13 появилась функция RelativeDateTimeFormatter
для возврата (локализованных) строк. относительно определенной даты.
Swift 3/4/5:
Calendar.current.isDateInToday(yourDate)
Calendar.current.isDateInYesterday(yourDate)
Calendar.current.isDateInTomorrow(yourDate)
Дополнительно:
Calendar.current.isDateInWeekend(yourDate)
Обратите внимание, что для некоторых стран выходные могут отличаться от субботы и воскресенья, это зависит от календаря.
Вы также можете использовать календарь autoupdatingCurrent
вместо current
, который будет отслеживать обновления пользователей. Вы используете его так же:
Calendar.autoupdatingCurrent.isDateInToday(yourDate)
Calendar
- это псевдоним типа для NSCalendar
.
1) Согласно вашему примеру вы хотите получать ярлыки «Вчера», «Сегодня» и т. Д. IOS может делать это по умолчанию:
2) Если вы хотите вычислить свой собственный ярлык, когда iOS не добавляет эти ярлыки отдельно, то в качестве альтернативы вы можете использовать 2 объекта DateFormatter
как с doesRelativeDateFormatting == true
, так и с doesRelativeDateFormatting == false
и сравнить их результат строки даты одинаковые или разные
У NSCalendar есть новые методы, которые вы можете использовать напрямую.
NSCalendar.currentCalendar().isDateInTomorrow(NSDate())//Replace NSDate() with your date
NSCalendar.currentCalendar().isDateInYesterday()
NSCalendar.currentCalendar().isDateInTomorrow()
Надеюсь это поможет
В Swift 5 и iOS 13 используйте RelativeDateTimeFormatter,
let formatter = RelativeDateTimeFormatter()
formatter.dateTimeStyle = .named
formatter.localizedString(from: DateComponents(day: -1)) // "yesterday"
formatter.localizedString(from: DateComponents(day: 1)) // "Tomorrow"
formatter.localizedString(from: DateComponents(hour: 2)) // "in 2 hours"
formatter.localizedString(from: DateComponents(minute: 45)) // "in 45 minutes"
Похожие вопросы
Связанные вопросы
Новые вопросы
ios
iOS - мобильная операционная система, работающая на Apple iPhone, iPod touch и iPad. Используйте этот тег [ios] для вопросов, связанных с программированием на платформе iOS. Используйте связанные теги [target-c] и [swift] для проблем, характерных для этих языков программирования.