Swift - iOS - Даты и время в разных форматах

Я работаю над приложением, написанным в swift, и я хочу манипулировать датами и временем

let timestamp = NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .ShortStyle, timeStyle: .ShortStyle)

возвращает

2/12/15, 11:27 PM

если я хочу дату и время в другом формате, например, дату в европейском формате, таком как dd/mm/yy, и часы в 24-часовом формате без AM и PM есть некоторая функция, которую я могу использовать или у меня есть использовать N строк для изменения порядка элементов?

Ответ 1

func convertDateFormater(date: String) -> String {   
    let dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
    dateFormatter.timeZone = NSTimeZone(name: "UTC")

    guard let date = dateFormatter.dateFromString(date) else {
        assert(false, "no date from string")
        return ""
    }

    dateFormatter.dateFormat = "yyyy MMM EEEE HH:mm"
    dateFormatter.timeZone = NSTimeZone(name: "UTC")
    let timeStamp = dateFormatter.stringFromDate(date)

    return timeStamp
}

Редактировать для Swift 4

func convertDateFormatter(date: String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"//this your string date format
    dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
    dateFormatter.locale = Locale(identifier: "your_loc_id")
    let convertedDate = dateFormatter.date(from: date)

    guard dateFormatter.date(from: date) != nil else {
        assert(false, "no date from string")
        return ""
    } 

    dateFormatter.dateFormat = "yyyy MMM HH:mm EEEE"///this is what you want to convert format
    dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
    let timeStamp = dateFormatter.string(from: convertedDate!)

    return timeStamp
}

Ответ 2

Как уже упоминалось, вы должны использовать DateFormatter для форматирования объектов Date. Самый простой способ сделать это - создать вычисляемое свойство Date extension только для чтения.


Вычисляемые свойства только для чтения

Вычисляемое свойство с получателем, но без установщика, известно как вычисляемое свойство только для чтения. Только для чтения вычисляемое свойство всегда возвращает значение и может быть доступно через точечный синтаксис, но не может быть установлено другое значение.

Замечания:

Вы должны объявить вычисляемые свойства - включая вычисляемые свойства только для чтения - как переменные свойства с ключевым словом var, потому что их значение не является фиксированным. Ключевое слово let используется только для константных свойств, чтобы указать, что их значения нельзя изменить, если они заданы как часть инициализации экземпляра.

Вы можете упростить объявление вычисляемого свойства только для чтения, удалив ключевое слово get и его фигурные скобки:


extension Formatter {
    static let date = DateFormatter()
}

extension Date {
    var europeanFormattedEn_US : String {
        Formatter.date.calendar = Calendar(identifier: .iso8601)
        Formatter.date.locale   = Locale(identifier: "en_US_POSIX")
        Formatter.date.timeZone = .current
        Formatter.date.dateFormat = "dd/M/yyyy, H:mm"
        return Formatter.date.string(from: self)
    }
}

Чтобы преобразовать его обратно, вы можете создать другое вычисляемое свойство только для чтения, но в виде расширения строки:

 extension String {
    var date: Date? {
        return Formatter.date.date(from: self)
    }
    func dateFormatted(with dateFormat: String = "dd/M/yyyy, H:mm", calendar: Calendar = Calendar(identifier: .iso8601), defaultDate: Date? = nil, locale: Locale = Locale(identifier: "en_US_POSIX"), timeZone: TimeZone = .current) -> Date? {
        Formatter.date.calendar = calendar
        Formatter.date.defaultDate = defaultDate ?? calendar.date(bySettingHour: 12, minute: 0, second: 0, of: Date())
        Formatter.date.locale = locale
        Formatter.date.timeZone = timeZone
        Formatter.date.dateFormat = dateFormat
        return Formatter.date.date(from: self)
    }
}

Использование:

let dateFormatted = Date().europeanFormattedEn_US         //"29/9/2018, 16:16"
if let date = dateFormatted.date {
    print(date.description(with:.current)) // Saturday, September 29, 2018 at 4:16:00 PM Brasilia Standard Time\n"\
    date.europeanFormattedEn_US                         // "29/9/2018, 16:27"
}

let dateString = "14/7/2016"
if let date = dateString.toDateFormatted(with: "dd/M/yyyy") {
    print(date.description(with: .current))
 // Thursday, July 14, 2016 at 12:00:00 PM Brasilia Standard Time\n"
}

Ответ 3

Как сказал Заф, вам нужно следовать документации. По общему признанию, это может быть не самым простым, по сравнению с другими классами. Короче говоря, вы используете таблицу символов поля даты, чтобы выяснить, какой формат вы хотите. Как только вы выполните:

let dateFormatter = NSDateFormatter()
//the "M/d/yy, H:mm" is put together from the Symbol Table
dateFormatter.dateFormat = "M/d/yy, H:mm"
dateFormatter.stringFromDate(NSDate())

Вам также нужно будет использовать таблицу, если вам нужно преобразовать дату, являющуюся строкой в ​​NSDate.

let dateAsString = "02/12/15, 16:48"
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "M/d/yyyy, H:mm"
let date = dateFormatter.dateFromString(dateAsString)

Ответ 4

Текущее время даты для форматированной строки:

let currentDate = Date()
let dateFormatter = DateFormatter()

dateFormatter.dateFormat = "dd/MM/yyyy hh:mm:ss a"
let convertedDate: String = dateFormatter.string(from: currentDate) //08/10/2016 01:42:22 AM

Больше форматов даты и времени

Ответ 5

Если вы хотите использовать протокол-ориентированное программирование (Swift 3)

1) Создать протокол с датой

protocol Dateable {
    func userFriendlyFullDate() -> String
    func userFriendlyHours() -> String
}

2) Расширить класс Date и реализовать протокол Dateable

extension Date: Dateable {
    var  formatter: DateFormatter { return DateFormatter() }

    /** Return a user friendly hour */
    func userFriendlyFullDate() -> String {
        // Customize a date formatter
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        formatter.timeZone = TimeZone(abbreviation: "UTC")

        return formatter.string(from: self)
    }

    /** Return a user friendly hour */
    func userFriendlyHours() -> String {
        // Customize a date formatter
        formatter.dateFormat = "HH:mm"
        formatter.timeZone = TimeZone(abbreviation: "UTC")

        return formatter.string(from: self)
    }

    // You can add many cases you need like string to date formatter

}

3) Используйте его

let currentDate: Date = Date()
let stringDate: String = currentDate.userFriendlyHours()
// Print 15:16

Ответ 7

Я использовал аналогичный подход как @iod07, но как расширение. Кроме того, я добавил некоторые пояснения в комментариях, чтобы понять, как это работает.

В принципе, просто добавьте это вверху или внизу вашего контроллера представления.

extension NSString {

class func convertFormatOfDate(date: String, originalFormat: String, destinationFormat: String) -> String! {

    // Orginal format :
    let dateOriginalFormat = NSDateFormatter()
    dateOriginalFormat.dateFormat = originalFormat      // in the example it'll take "yy MM dd" (from our call)

    // Destination format :
    let dateDestinationFormat = NSDateFormatter()
    dateDestinationFormat.dateFormat = destinationFormat // in the example it'll take "EEEE dd MMMM yyyy" (from our call)

    // Convert current String Date to NSDate
    let dateFromString = dateOriginalFormat.dateFromString(date)

    // Convert new NSDate created above to String with the good format
    let dateFormated = dateDestinationFormat.stringFromDate(dateFromString!)

    return dateFormated

}
}

Пример

Предположим, вы хотите преобразовать "16 05 05" в "Thursday 05 May 2016", и ваша дата будет объявлена ​​следующим образом: let date = "16 06 05"

Затем просто вызовите его с помощью:

let newDate = NSString.convertFormatOfDate(date, originalFormat: "yy MM dd", destinationFormat: "EEEE dd MMMM yyyy")

Надеюсь, что это поможет!

Ответ 8

Swift 3:

//This gives month as three letters (Jun, Dec, etc)
let justMonth = DateFormatter()
justMonth.dateFormat = "MMM"
myFirstLabel.text = justMonth.string(from: myDate)

//This gives the day of month, with no preceding 0s (6,14,29)
let justDay = DateFormatter()
justDay.dateFormat = "d"
mySecondLabel.text = justDay.string(from: myDate)

//This gives year as two digits, preceded by an apostrophe ('09, '16, etc)
let justYear = DateFormatter()
justYear.dateFormat = "yy"
myThirdLabel.text = "'\(justYear.string(from: lastCompDate))"

Для получения дополнительных форматов ознакомьтесь с этой ссылкой в таблице codingExplorer со всеми доступными форматами. Каждый компонент даты имеет несколько параметров, например:

Год:

  • "y" - 2016 (ранние даты, такие как год 1, будут: "1" ).
  • "yy" - 16 (год 1: "01"
  • "yyy" - 2016 (год 1: "001" )
  • "yyyy" - 2016 (год 1: "0001" )

Практически каждый компонент имеет 2-4 варианта, используя первую букву для выражения формата (день "d", час - "h" и т.д.). Однако месяц является капиталом "М", потому что нижний регистр "м" зарезервирован на минуту. Однако есть и другие исключения, поэтому проверьте ссылку!

Ответ 9

Вот решение, которое работает с Xcode 10.1 (23 Фев 2019):

func getCurrentDateTime() {

    let now = Date()
    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "fr_FR")
    formatter.dateFormat = "EEEE dd MMMM YYYY"
    labelDate.text = formatter.string(from: now)
    labelDate.font = UIFont(name: "HelveticaNeue-Bold", size: 12)
    labelDate.textColor = UIColor.lightGray

    let text = formatter.string(from: now)
    labelDate.text = text.uppercased()
}

Ярлык "Accueil" не связан с кодом.

Ответ 10

let usDateFormat = DateFormatter.dateFormat(FromTemplate: "MMddyyyy", options: 0, locale: Locale(identifier: "en-US"))
            //usDateFormat now contains an optional string "MM/dd/yyyy"

let gbDateFormat = DateFormatter.dateFormat(FromTemplate: "MMddyyyy", options: 0, locale: Locale(identifier: "en-GB"))
            //gbDateFormat now contains an optional string "dd/MM/yyyy"

let geDateFormat = DateFormatter.dateFormat(FromTemplate: "MMddyyyy", options: 0, locale: Locale(identifier: "de-DE"))
            //geDateFormat now contains an optional string "dd.MM.yyyy"

Вы можете использовать его следующим образом, чтобы получить текущий формат с устройства:

let currentDateFormat = DateFormatter.dateFormat(fromTemplate: "MMddyyyy", options: 0, locale: Locale.current)

Ответ 11

let dateString = "1970-01-01T13:30:00.000Z"
let formatter = DateFormatter()

formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
let date = formatter.date(from: String(dateString.dropLast(5)))!
formatter.dateFormat = "hh.mma"
print(formatter.string(from: date))

если вы заметили, что я установил .dateFormat = "hh.mma", вы получите только время. Результат: 01.30PM

Ответ 12

extension String {

    func convertDatetring_TopreferredFormat(currentFormat: String, toFormat : String) ->  String {
        let dateFormator = DateFormatter()
        dateFormator.dateFormat = currentFormat
        let resultDate = dateFormator.date(from: self)
        dateFormator.dateFormat = toFormat
        return dateFormator.string(from: resultDate!)
    }

}

Звоните из файла контроллера представления, как показано ниже.

"your_date_string".convertDatetring_TopreferredFormat(currentFormat: "yyyy-MM-dd HH:mm:ss.s", toFormat: "dd-MMM-yyyy h:mm a")

Ответ 13

Возможно, это старая ветка, но я недавно работал над датами и столкнулся с аналогичной проблемой, поэтому в итоге я создал свою утилиту, которая выглядит следующим образом:

Эта утилита будет принимать строковую дату и будет возвращать необязательный объект даты

        func toDate(dateFormat: DateFormatType) -> Date? {
        let formatter = DateFormatter()
        formatter.timeZone = NSTimeZone(name: "UTC") as TimeZone?
        formatter.dateFormat = dateFormat.rawValue
        let temp = formatter.date(from: self)
        return formatter.date(from: self)
        }

перечисление DateFormatType выглядит следующим образом

        enum DateFormatType : String {
        case type1 = "yyyy-MM-dd - HH:mm:ss"
        case type2 = "dd/MM/yyyy"
        case type3 = "yyyy/MM/dd"
    }

Одна важная вещь, которую я хотел бы упомянуть здесь, это строка

formatter.timeZone = NSTimeZone(name: "UTC") as TimeZone?

очень важно добавить эту строку, потому что без этого DateFormatter будет использовать преобразования по умолчанию для преобразования даты, и вы можете в конечном итоге увидеть разные даты, если вы работаете с удаленной командой и получаете всевозможные проблемы с данными в зависимости от даты.

Надеюсь это поможет

Ответ 14

iOS 8+

Это громоздко и трудно определить locale explicitly. Вы никогда не знаете, где будет использоваться ваше приложение. Поэтому я думаю, что лучше установить locale на Calender.current.locale и использовать DateFormatter setLocalizedDateFormatFromTemplate метод.

setLocalizedDateFormatFromTemplate (_ :)

Устанавливает формат даты из шаблона, используя указанную локаль для получателя. - developer.apple.com

extension Date {
    func convertToLocaleDate(template: String) -> String {
        let dateFormatter = DateFormatter()

        let calender = Calendar.current

        dateFormatter.timeZone = calender.timeZone
        dateFormatter.locale = calender.locale
        dateFormatter.setLocalizedDateFormatFromTemplate(template)

        return dateFormatter.string(from: self)
    }
}



Date().convertToLocaleDate(template: "dd MMMM YYYY")