Swift конвертировать время назад
Я пытаюсь преобразовать время от времени, что я хочу сделать, это:
от 1 до 15 секунд будет написано "Только сейчас"
от 60 минут до 119 минут он скажет "час назад"
с 24 до 47 часов будет сказано "вчера"
с 7 дней до 7 дней и 23 часов будет сказано "неделю назад"
Я не уверен в своем подсчете, если я ошибаюсь, не стесняйтесь исправить это для меня
Вот код
extension NSDate {
struct Date {
static let timeFormatter: NSDateFormatter = {
let df = NSDateFormatter()
df.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
df.dateFormat = "h:mm a"
return df
}()
}
var time: String { return Date.timeFormatter.stringFromDate(self) }
var year: Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Year, fromDate: self) }
var month: Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Month, fromDate: self) }
var day: Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Day, fromDate: self) }
var hour: Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Hour, fromDate: self) }
var minute: Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Minute, fromDate: self) }
var second: Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Second, fromDate: self) }
struct DateComponents {
static let formatter: NSDateComponentsFormatter = {
let dcFormatter = NSDateComponentsFormatter()
dcFormatter.calendar = NSCalendar(identifier: NSCalendarIdentifierISO8601)!
dcFormatter.unitsStyle = .Full
dcFormatter.maximumUnitCount = 1
dcFormatter.zeroFormattingBehavior = .Default
dcFormatter.allowsFractionalUnits = false
dcFormatter.allowedUnits = [.Year, .Month, .Weekday, .Day, .Hour, .Minute, .Second]
return dcFormatter
}()
}
var elapsedTime: String {
if isecond(NSDate()) {
return "Just now"
}
if ishour(NSDate()) {
return "an hour ago"
}
if isyesterday(NSDate()) {
return "Yesterday"
}
if isweek(NSDate()) {
return "a week ago"
}
return (DateComponents.formatter.stringFromTimeInterval(NSDate().timeIntervalSinceDate(self)) ?? "") + " ago"
}
func isyesterday(date: NSDate) -> Bool {
return NSCalendar.autoupdatingCurrentCalendar().isDate(self, inSameDayAsDate: date.yesterday)
}
var yesterday: NSDate {
return NSCalendar.autoupdatingCurrentCalendar().dateWithEra(1, year: year, month: month, day: day-1, hour: 0, minute: 0, second: 0, nanosecond: 0)!
}
func isweek(date: NSDate) -> Bool {
return NSCalendar.autoupdatingCurrentCalendar().isDate(self, inSameDayAsDate: date.weekago)
}
var weekago: NSDate {
return NSCalendar.autoupdatingCurrentCalendar().dateWithEra(1, year: year, month: month, day: day-7, hour: 0, minute: 0, second: 0, nanosecond: 0)!
}
func isecond(date: NSDate) -> Bool {
return NSCalendar.autoupdatingCurrentCalendar().isDate(self, inSameDayAsDate: date.secondsago)
}
var secondsago: NSDate {
return NSCalendar.autoupdatingCurrentCalendar().dateWithEra(1, year: year, month: month, day: 0, hour: 0, minute: 0, second: second-15, nanosecond: 0)!
}
func ishour(date: NSDate) -> Bool {
return NSCalendar.autoupdatingCurrentCalendar().isDate(self, inSameDayAsDate: date.hourago)
}
var hourago: NSDate {
return NSCalendar.autoupdatingCurrentCalendar().dateWithEra(1, year: year, month: month, day: 0, hour: hour-1, minute: minute-1, second: 0, nanosecond: 0)!
}
}
вот что я получил в своем приложении:
![enter image description here]()
цитаты "час назад", "только сейчас" и т.д. не отображаются, только "вчера", и я не уверен, что это только от 7 дней до 23 часов!
и вот моя первая ссылка на вопрос: Swift Как конвертировать Parse, созданный время от времени?
Пожалуйста, помогите мне исправить код,
спасибо @Leo Dabus за код.
Ответы
Ответ 1
Я просто обновлю ответ Truongky для Swif 3:
extension Date {
func getElapsedInterval() -> String {
let interval = Calendar.current.dateComponents([.year, .month, .day], from: self, to: Date())
if let year = interval.year, year > 0 {
return year == 1 ? "\(year)" + " " + "year ago" :
"\(year)" + " " + "years ago"
} else if let month = interval.month, month > 0 {
return month == 1 ? "\(month)" + " " + "month ago" :
"\(month)" + " " + "months ago"
} else if let day = interval.day, day > 0 {
return day == 1 ? "\(day)" + " " + "day ago" :
"\(day)" + " " + "days ago"
} else {
return "a moment ago"
}
}
}
Если вы предпочитаете локализованный ответ, а не только английский, этот код будет работать
extension Date {
func getElapsedInterval() -> String {
var calendar = Calendar.current
calendar.locale = Locale(identifier: Bundle.main.preferredLocalizations[0])
// IF THE USER HAVE THE PHONE IN SPANISH BUT YOUR APP ONLY SUPPORTS I.E. ENGLISH AND GERMAN
// WE SHOULD CHANGE THE LOCALE OF THE FORMATTER TO THE PREFERRED ONE
// (IS THE LOCALE THAT THE USER IS SEEING THE APP), IF NOT, THIS ELAPSED TIME
// IS GOING TO APPEAR IN SPANISH
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.maximumUnitCount = 1
formatter.calendar = calendar
var dateString: String?
let interval = calendar.dateComponents([.year, .month, .weekOfYear, .day], from: self, to: Date())
if let year = interval.year, year > 0 {
formatter.allowedUnits = [.year] //2 years
} else if let month = interval.month, month > 0 {
formatter.allowedUnits = [.month] //1 month
} else if let week = interval.weekOfYear, week > 0 {
formatter.allowedUnits = [.weekOfMonth] //3 weeks
} else if let day = interval.day, day > 0 {
formatter.allowedUnits = [.day] // 6 days
} else {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: Bundle.main.preferredLocalizations[0]) //--> IF THE USER HAVE THE PHONE IN SPANISH BUT YOUR APP ONLY SUPPORTS I.E. ENGLISH AND GERMAN WE SHOULD CHANGE THE LOCALE OF THE FORMATTER TO THE PREFERRED ONE (IS THE LOCALE THAT THE USER IS SEEING THE APP), IF NOT, THIS ELAPSED TIME IS GOING TO APPEAR IN SPANISH
dateFormatter.dateStyle = .medium
dateFormatter.doesRelativeDateFormatting = true
dateString = dateFormatter.string(from: self) // IS GOING TO SHOW 'TODAY'
}
if dateString == nil {
dateString = formatter.string(from: self, to: Date())
}
return dateString!
}
Ответ 2
Версия Swift 4+
extension Date {
func timeAgoSinceDate() -> String {
// From Time
let fromDate = self
// To Time
let toDate = Date()
// Estimation
// Year
if let interval = Calendar.current.dateComponents([.year], from: fromDate, to: toDate).year, interval > 0 {
return interval == 1 ? "\(interval)" + " " + "year ago" : "\(interval)" + " " + "years ago"
}
// Month
if let interval = Calendar.current.dateComponents([.month], from: fromDate, to: toDate).month, interval > 0 {
return interval == 1 ? "\(interval)" + " " + "month ago" : "\(interval)" + " " + "months ago"
}
// Day
if let interval = Calendar.current.dateComponents([.day], from: fromDate, to: toDate).day, interval > 0 {
return interval == 1 ? "\(interval)" + " " + "day ago" : "\(interval)" + " " + "days ago"
}
// Hours
if let interval = Calendar.current.dateComponents([.hour], from: fromDate, to: toDate).hour, interval > 0 {
return interval == 1 ? "\(interval)" + " " + "hour ago" : "\(interval)" + " " + "hours ago"
}
// Minute
if let interval = Calendar.current.dateComponents([.minute], from: fromDate, to: toDate).minute, interval > 0 {
return interval == 1 ? "\(interval)" + " " + "minute ago" : "\(interval)" + " " + "minutes ago"
}
return "a moment ago"
}
}
использование
yourDate.timeAgoSinceDate()
Ответ 3
Измените текст так, как хотите.
extension NSDate {
func getElapsedInterval() -> String {
var interval = NSCalendar.currentCalendar().components(.Year, fromDate: self, toDate: NSDate(), options: []).year
if interval > 0 {
return interval == 1 ? "\(interval)" + " " + "year" :
"\(interval)" + " " + "years"
}
interval = NSCalendar.currentCalendar().components(.Month, fromDate: self, toDate: NSDate(), options: []).month
if interval > 0 {
return interval == 1 ? "\(interval)" + " " + "month" :
"\(interval)" + " " + "months"
}
interval = NSCalendar.currentCalendar().components(.Day, fromDate: self, toDate: NSDate(), options: []).day
if interval > 0 {
return interval == 1 ? "\(interval)" + " " + "day" :
"\(interval)" + " " + "days"
}
interval = NSCalendar.currentCalendar().components(.Hour, fromDate: self, toDate: NSDate(), options: []).hour
if interval > 0 {
return interval == 1 ? "\(interval)" + " " + "hour" :
"\(interval)" + " " + "hours"
}
interval = NSCalendar.currentCalendar().components(.Minute, fromDate: self, toDate: NSDate(), options: []).minute
if interval > 0 {
return interval == 1 ? "\(interval)" + " " + "minute" :
"\(interval)" + " " + "minutes"
}
return "a moment ago"
}
}
Ответ 4
Swift 3 версия кода truongky:
extension Date {
var timeAgoSinceNow: String {
return getTimeAgoSinceNow()
}
private func getTimeAgoSinceNow() -> String {
var interval = Calendar.current.dateComponents([.year], from: self, to: Date()).year!
if interval > 0 {
return interval == 1 ? "\(interval)" + " year" : "\(interval)" + " years"
}
interval = Calendar.current.dateComponents([.month], from: self, to: Date()).month!
if interval > 0 {
return interval == 1 ? "\(interval)" + " month" : "\(interval)" + " months"
}
interval = Calendar.current.dateComponents([.day], from: self, to: Date()).day!
if interval > 0 {
return interval == 1 ? "\(interval)" + " day" : "\(interval)" + " days"
}
interval = Calendar.current.dateComponents([.hour], from: self, to: Date()).hour!
if interval > 0 {
return interval == 1 ? "\(interval)" + " hour" : "\(interval)" + " hours"
}
interval = Calendar.current.dateComponents([.minute], from: self, to: Date()).minute!
if interval > 0 {
return interval == 1 ? "\(interval)" + " minute" : "\(interval)" + " minutes"
}
return "a moment ago"
}
}
Ответ 5
Использование даты вместо NSDate: Ответ от:
func timeAgoSinceDate(_ date:Date, numericDates:Bool = false) -> String {
let calendar = NSCalendar.current
let unitFlags: Set<Calendar.Component> = [.minute, .hour, .day, .weekOfYear, .month, .year, .second]
let now = Date()
let earliest = now < date ? now : date
let latest = (earliest == now) ? date : now
let components = calendar.dateComponents(unitFlags, from: earliest, to: latest)
if (components.year! >= 2) {
return "\(components.year!) years ago"
} else if (components.year! >= 1){
if (numericDates){
return "1 year ago"
} else {
return "Last year"
}
} else if (components.month! >= 2) {
return "\(components.month!) months ago"
} else if (components.month! >= 1){
if (numericDates){
return "1 month ago"
} else {
return "Last month"
}
} else if (components.weekOfYear! >= 2) {
return "\(components.weekOfYear!) weeks ago"
} else if (components.weekOfYear! >= 1){
if (numericDates){
return "1 week ago"
} else {
return "Last week"
}
} else if (components.day! >= 2) {
return "\(components.day!) days ago"
} else if (components.day! >= 1){
if (numericDates){
return "1 day ago"
} else {
return "Yesterday"
}
} else if (components.hour! >= 2) {
return "\(components.hour!) hours ago"
} else if (components.hour! >= 1){
if (numericDates){
return "1 hour ago"
} else {
return "An hour ago"
}
} else if (components.minute! >= 2) {
return "\(components.minute!) minutes ago"
} else if (components.minute! >= 1){
if (numericDates){
return "1 minute ago"
} else {
return "A minute ago"
}
} else if (components.second! >= 3) {
return "\(components.second!) seconds ago"
} else {
return "Just now"
}
}
Как использовать
var createdDate : String = "123232323" //time stamp
var createdDataDisplayString: String {
let date = Date(timeIntervalSince1970: Double(self.createdDate)!).timeAgoSinceDate(numericDates: true)
return "\(date)"
}
print(self.createdDataDisplayString)
Ответ 6
Swift 4.1. Передайте дату в параметре функции, и функция вернется в прошлое время.
func getPastTime(for date : Date) -> String {
var secondsAgo = Int(Date().timeIntervalSince(date))
if secondsAgo < 0 {
secondsAgo = secondsAgo * (-1)
}
let minute = 60
let hour = 60 * minute
let day = 24 * hour
let week = 7 * day
if secondsAgo < minute {
if secondsAgo < 2{
return "just now"
}else{
return "\(secondsAgo) secs ago"
}
} else if secondsAgo < hour {
let min = secondsAgo/minute
if min == 1{
return "\(min) min ago"
}else{
return "\(min) mins ago"
}
} else if secondsAgo < day {
let hr = secondsAgo/hour
if hr == 1{
return "\(hr) hr ago"
} else {
return "\(hr) hrs ago"
}
} else if secondsAgo < week {
let day = secondsAgo/day
if day == 1{
return "\(day) day ago"
}else{
return "\(day) days ago"
}
} else {
let formatter = DateFormatter()
formatter.dateFormat = "MMM dd, hh:mm a"
formatter.locale = Locale(identifier: "en_US")
let strDate: String = formatter.string(from: date)
return strDate
}
}
Ответ 7
Мои потребности проще, либо "сейчас", либо "х назад",
С iOS 8 вы можете использовать (NS) DateComponentsFormatter
func getElapsedInterval() -> String {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.minute, .hour, .day, .month, .year]
formatter.unitsStyle = .abbreviated
formatter.zeroFormattingBehavior = .dropAll
formatter.maximumUnitCount = 1
var dateString: String?
if self.timeIntervalSince(Date()) > -60*5 {
dateString = NSLocalizedString("now", comment: "")
} else {
dateString = String.init(format: NSLocalizedString("%@ ago", comment: ""), locale: .current, formatter.string(from: self, to: Date())!)
}
return dateString ?? ""
}
например
var date = Date.init(timeIntervalSinceNow: -60)
print(date.getElapsedInterval())
date = Date.init(timeIntervalSinceNow: -60*10)
print(date.getElapsedInterval())
date = Date.init(timeIntervalSinceNow: -60*60)
print(date.getElapsedInterval())
date = Date.init(timeIntervalSinceNow: -60*60*24)
print(date.getElapsedInterval())
date = Date.init(timeIntervalSinceNow: -60*60*24*30)
print(date.getElapsedInterval())
date = Date.init(timeIntervalSinceNow: -60*60*24*31*12)
print(date.getElapsedInterval())
сейчас
10 мин. Назад
1 час назад
1 день назад
1 минуту назад
1 год назад
Ответ 8
Вы должны добавить это расширение даты в свой вспомогательный класс или любой из файлов быстрого доступа. Swift 4.2. если вы хотите в быстром 3, просто раскомментируйте прокомментированную строку и прокомментируйте следующую строку.
И вызовите метод следующим образом:
let dateText = Date().offsetFrom(date: yourDate!)
yourDate - дата, которая должна быть изменена
////MARK: *************** Extension Date ***************
extension Date{
func convertToString(validDateFormatter:String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = validDateFormatter //"dd MMM yyyy" //yyyy-mm-dd hh:mm
//return dateFormatter.stringFromDate(self)
return dateFormatter.string(from: self as Date)
}
func yearsFrom(date:Date) -> Int{
// return NSCalendar.currentCalendar.components(.Year, fromDate: date, toDate: self, options: []).year
// let calendar = NSCalendar.current
// let components = Calendar.current.dateComponents([.year], from: date, to: self as Date)
return Calendar.current.dateComponents([.year], from: date, to: self).year!
}
func monthsFrom(date:Date) -> Int{
// return NSCalendar.currentCalendar.components(.Month, fromDate: date, toDate: self, options: []).month
return Calendar.current.dateComponents([.month], from: date as Date, to: self).month!
}
func weeksFrom(date:Date) -> Int{
//return NSCalendar.currentCalendar.components(.WeekOfYear, fromDate: date, toDate: self, options: []).weekOfYear
return Calendar.current.dateComponents([.weekOfYear], from: date, to: self).weekOfYear!
}
func daysFrom(date:Date) -> Int{
// return NSCalendar.currentCalendar.components(.Day, fromDate: date, toDate: self, options: []).day
return Calendar.current.dateComponents([.day], from: date, to: self).day!
}
func hoursFrom(date:Date) -> Int{
// return NSCalendar.currentCalendar.components(.Hour, fromDate: date, toDate: self, options: []).hour
return Calendar.current.dateComponents([.hour], from: date, to: self).hour!
}
func minutesFrom(date:Date) -> Int{
// return NSCalendar.currentCalendar.components(.Minute, fromDate: date, toDate: self, options: []).minute
return Calendar.current.dateComponents([.minute], from: date, to: self).minute!
}
func secondsFrom(date:Date) -> Int{
// return NSCalendar.currentCalendar.components(.Second, fromDate: date, toDate: self, options: []).second
return Calendar.current.dateComponents([.second], from: date, to: self).second!
}
func offsetFrom(date:Date) -> String
{
if yearsFrom(date: date) > 0 {
return "\(yearsFrom(date: date))y"
}
if monthsFrom(date: date) > 0 {
return "\(monthsFrom(date: date))M"
}
if weeksFrom(date: date) > 0{
return "\(weeksFrom(date: date))w"
}
if daysFrom(date: date) > 0 {
return "\(daysFrom(date: date))d"
}
if hoursFrom(date: date) > 0 {
return "\(hoursFrom(date: date))h"
}
if minutesFrom(date: date) > 0 {
return "\(minutesFrom(date: date))m"
}
if secondsFrom(date: date) > 0 {
return "\(secondsFrom(date: date))s"
}
return ""
}
}
Ответ 9
Вот решение, которое вы можете скопировать вставить
func timeAgoSinceDate(_ date:Date, numericDates:Bool = false) -> String? {
let calendar = NSCalendar.current
let unitFlags: Set<Calendar.Component> = [.minute, .hour, .day, .weekOfYear, .month, .year, .second]
let now = Date()
let earliest = now < date ? now : date
let latest = (earliest == now) ? date : now
let components = calendar.dateComponents(unitFlags, from: earliest, to: latest)
if (components.year! >= 2) {
return "\(components.year!)yr"
} else if (components.year! >= 1){
if (numericDates){
return "1yr"
} else {
return "Last year"
}
} else if (components.month! >= 2) {
return "\(components.month!)mo"
} else if (components.month! >= 1){
if (numericDates){
return "1 mo"
} else {
return "Last mo"
}
} else if (components.weekOfYear! >= 2) {
return "\(components.weekOfYear!) weeks"
} else if (components.weekOfYear! >= 1){
if (numericDates){
return "1 week"
} else {
return "Last week"
}
} else if (components.day! >= 2) {
return "\(components.day!) d"
} else if (components.day! >= 1){
if (numericDates){
return "1 d"
} else {
return "1 d"
}
} else if (components.hour! >= 2) {
return "\(components.hour!) hrs"
} else if (components.hour! >= 1){
if (numericDates){
return "1 hr"
} else {
return "1 hr"
}
} else if (components.minute! >= 2) {
return "\(components.minute!) m"
} else if (components.minute! >= 1){
if (numericDates){
return "1 m"
} else {
return "2 m"
}
} else if (components.second! >= 3) {
return "\(components.second!)s"
} else {
return "now"
}
}
чтобы позвонить, просто используйте
// the date you are getting information about
let dateToReference = Date()
if let timeAgo = timeAgoSinceDate(dateToReference) {
//will be a String value
print(timeAgo)
} else {
//just in case something goes wrong
print("recently")
}
Ответ 10
Swift 4 версия честного кода:
И добавить опционально для TimeEnd не сейчас.
extension Date {
func getElapsedInterval(to end: Date = Date()) -> String {
if let interval = Calendar.current.dateComponents([Calendar.Component.year], from: self, to: end).day {
if interval > 0 {
return "\(interval) year\(interval == 1 ? "":"s")"
}
}
if let interval = Calendar.current.dateComponents([Calendar.Component.month], from: self, to: end).month {
if interval > 0 {
return "\(interval) month\(interval == 1 ? "":"s")"
}
}
if let interval = Calendar.current.dateComponents([Calendar.Component.weekOfMonth], from: self, to: end).weekOfMonth {
if interval > 0 {
return "\(interval) week\(interval == 1 ? "":"s")"
}
}
if let interval = Calendar.current.dateComponents([Calendar.Component.day], from: self, to: end).day {
if interval > 0 {
return "\(interval) day\(interval == 1 ? "":"s")"
}
}
if let interval = Calendar.current.dateComponents([Calendar.Component.hour], from: self, to: end).hour {
if interval > 0 {
return "\(interval) hour\(interval == 1 ? "":"s")"
}
}
if let interval = Calendar.current.dateComponents([Calendar.Component.minute], from: self, to: end).minute {
if interval > 0 {
return "\(interval) minute\(interval == 1 ? "":"s")"
}
}
return "Just now."
}
}
Ответ 11
На Swift 5 используйте RelativeDateTimeFormatter,
let formatter = RelativeDateTimeFormatter()
formatter.localizedString(from: DateComponents(day: -1)) // "1 day ago"
formatter.localizedString(from: DateComponents(hour: 2)) // "in 2 hours"
formatter.localizedString(from: DateComponents(minute: 45)) // "in 45 minutes"
установить dateTimeStyle получить локализованные дейстические заявления, например, -
formatter.dateTimeStyle = .named
formatter.localizedString(from: DateComponents(day: -1)) // "yesterday"