Как отобразить дату с человеческим языком, например "Сегодня в xx: xx pm", "Вчера в xx: xx am"?

У меня есть дата "2014-07-02 20:57:38 +0000", и я хочу отформатировать ее как "Сегодня в 20:57". Я хочу, чтобы, если строка вчера, а затем отобразите ее как "Вчера в 9:00". Если это не сегодня или вчера, просто покажите фактическую дату, например "27/6 в 7:53".

Я смог получить время с форматом типа "8:57 AM" с кодом ниже.

            var formatter : NSDateFormatter = NSDateFormatter()
            formatter.dateFormat = "h:mm a"

            // message.createdAt is the date
            let dateString = formatter.stringFromDate(message.createdAt)
            println(dateString)

            //output = 8:57 AM

Однако, когда я использую следующий код, он возвращает пустую строку.

            var formatter : NSDateFormatter = NSDateFormatter()
            formatter.dateFormat = "h:mm a"
            formatter.doesRelativeDateFormatting = true  //<-- This doesn't work

            let dateString = formatter.stringFromDate(message.createdAt)
            println(dateString)

            //output = (nothing, its a blank string)

Как мне сделать эту работу и отображать "Сегодня" или "Вчера" в Swift?

Ответ 1

Причина в том, что формат даты имеет только компоненты времени. В сочетании с .doesRelativeDateFormatting, который дает пустую строку. Если вам нужен этот формат времени, я думаю, вам нужны отдельные форматиры для даты и времени:

let now = NSDate()

let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .MediumStyle
dateFormatter.doesRelativeDateFormatting = true

let timeFormatter = NSDateFormatter()
timeFormatter.dateFormat = "h:mm a"

let time = "\(dateFormatter.stringFromDate(now)), \(timeFormatter.stringFromDate(now))"
println(time)      // prints "Today, 5:10 PM"

Ответ 2

С Swift 3 в Справочнике API разработчика Apple говорится о DateFormatter dateFormat свойство:

Вы должны установить это свойство только при работе с представлениями с фиксированным форматом, как описано в Работа с фиксированными форматными представлениями даты. Для видимых пользователем представлений вы должны использовать dateStyle и timeStyle или setLocalizedDateFormatFromTemplate (_:), если желаемый формат не может быть достигнут с использованием предопределенных стилей; оба этих свойства и этот метод обеспечивают локализованное представление даты, соответствующее отображению пользователю.


DateFormatter dateStyle свойство имеет следующее объявление:

Стиль даты приемника.

var dateStyle: DateFormatter.Style { get set }

Таким же образом свойство DateFormatter timeStyle имеет следующее объявление:

Стиль времени приемника.

var timeStyle: DateFormatter.Style { get set }

Обратите внимание, что DateFormatter.Style представляет собой перечисление со следующими случаями: none, short, medium, long, full.

Также обратите внимание, что doesRelativeDateFormatting работает только при установке dateStyle и/или timeStyle для экземпляра DateFormatter.


Следующий код площадки показывает, как отображать даты в нужном формате с помощью свойств DateFormatter dateStyle и timeStyle.

import Foundation

let now = Date() // 2017-03-12 14:53:34 +0000
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: now)! // 2017-03-11 14:53:34 +0000
let aWeekAgo = Calendar.current.date(byAdding: .weekOfMonth, value: -1, to: now)! // 2017-03-05 14:53:34 +0000

let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .short
dateFormatter.doesRelativeDateFormatting = true

let nowString = dateFormatter.string(from: now)
print(nowString) // prints: Today at 3:53 PM

let yesterdayString = dateFormatter.string(from: yesterday)
print(yesterdayString) // prints: Yesterday at 3:53 PM

let aWeekAgoString = dateFormatter.string(from: aWeekAgo)
print(aWeekAgoString) // prints: March 5, 2017 at 3:53 PM

Ответ 3

Попробуйте

let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .ShortStyle
dateFormatter.timeStyle = .ShortStyle
dateFormatter.doesRelativeDateFormatting = true

let date = NSDate()
let dateString = dateFormatter.stringFromDate(date)