Использование DateFormatter дает результат, который отличается на день (фактически на 12 часов). Использование следующего кода последовательно создает даты, которые отображаются как предыдущий день. Некоторое время я получал это в ряде приложений, но только что наконец нашел время покопаться в этом.

extension Date
{
    func display() -> String
    {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMMM dd, yyyy"
        print(dateFormatter.locale)
        dateFormatter.locale = Locale(identifier: "en_US_POSIX")
        let txt = dateFormatter.string(from: self)
        print(txt)
        return txt
    }
}

Другие вопросы, которые были в этом ключе, предлагали изменить языковой стандарт, следовательно, добавленный код для этого, но я проверил языковой стандарт и фактическую дату. Если я добавлю 8 часов к дате, я получу правильный результат отображения, но добавление меньшего количества ничего не даст. Некоторые даты извлекаются из поля дня рождения в приложении "Контакты", что дает даты с временем суток 00:00:00 UTC. Казалось бы, мне нужно перевести дату на местное время? Часовой пояс на устройстве установлен на местный часовой пояс (Тихий океан). Это не выглядело бы так плохо, но даты, полученные с помощью средства выбора даты, находятся не в UTC, а в местном времени. Я не смог понять, как определить, в каком часовом поясе находится дата, так как использование класса календаря и попытка извлечь компонент .timezone говорят, что «NSCalendarUnitTimeZone не может быть получен этим методом». Есть предложения по созданию универсального средства форматирования даты, которое будет работать во всех случаях?

1
RTB 2 Янв 2018 в 22:41

2 ответа

Лучший ответ

Пара наблюдений:

  1. Если ваш объект Date находится в часовом поясе UTC, установите для timeZone средства форматирования значение TimeZone(secondsFromGMT: 0) тоже.

  2. Если вы показываете строковое представление объекта Date в пользовательском интерфейсе, вы не хотите использовать locale из en_US_POSIX. Вы хотите, чтобы это отображалось в местоположении устройства по умолчанию (т.е. вообще не меняйте locale форматтера). Вы используете en_US_POSIX только при работе со строками даты ISO 8601 и RFC 3339, которые используются внутри компании или, например, для обмена строками даты с веб-службой).

  3. Наконец, я бы не стал указывать строку dateFormat, потому что не все пользователи ожидают даты в формате MMMM dd, yyyy. Например, пользователи Великобритании ожидают его в формате d MMMM yyyy. При представлении дат в пользовательском интерфейсе вместо этого укажите dateStyle. Или, если ни один из этих стилей не работает, укажите dateFormat, но установите его с помощью setLocalizedDateFormatFromTemplate(_:), а не фиксированная строка.

Таким образом, для вашей цели вы должны:

extension Date {
    var dateString: String {
        let formatter = DateFormatter()
        formatter.dateStyle = .long
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        return formatter.string(from: self)
    }
}

Или, если вы часто вызываете это, вы можете повторно использовать средство форматирования:

extension Date {

    private static let formatterForDateString: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .long
        formatter.timeZone = TimeZone(secondsFromGMT: 0)

        return formatter
    }()

    var dateString: String {
        return Date.formatterForDateString.string(from: self)
    }

}
1
Rob 2 Янв 2018 в 20:46

Используйте свойство timeZone, чтобы получить точную дату, как показано ниже:

    formatter.timeZone = TimeZone(secondsFromGMT: 0)

Это решит вашу цель!

0
Madhur 3 Янв 2018 в 07:36