WedX - журнал о программировании и компьютерных науках

Swift 4: установить другую дату и время

Я знаю, как получить местную дату и время, но я хочу получить дату и время из разных мест. Например, я хочу узнать, какое время и дата в Нью-Йорке. Как я могу решить эту простую проблему?

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

let date = NSDate()
let calendar = Calendar.current

let components = calendar.dateComponents([.hour, .minute, .month, .year, .day, .second, .weekOfMonth], from: date as Date)

let currentDate = calendar.date(from: components) 

Я искал об этом здесь, но я не нашел то, что хочу, и я все еще ищу библиотеки дат. Если вы знаете какой-либо источник или образец, чтобы перенаправить меня, я очень ценю это.


  • Календарь имеет свойство timeZone.... 13.11.2017
  • @MartinR Но это только для чтения, не так ли? 13.11.2017
  • @Sweeper: Нет, это не так (если только вы не определите календарь как константу с помощью let :) 13.11.2017
  • Если ваша цель - это что-то вроде словесных часов, все, что вам нужно, это установить другой часовой пояс в вашем форматировщике даты. Нет необходимости добавлять временной интервал, как предлагает Zig. 14.11.2017

Ответы:


1

Здесь задействовано несколько разных концепций, и нам нужно понять (почти) все из них, чтобы понять это правильно...

1) Date (NSDate как было в Swift) — это абсолютный момент времени — он немного неправильно назван, потому что он не имеет ничего общего с фактической датой, такой как 13 ноября 2017 года, потому что для этого нам нужно определить . ..

2) a Calendar, потому что 13 ноября 2017 года по западному григорианскому календарю также может быть 23-м сафаром 1439 года по исламскому календарю, или 24-м числом хешвана 5778 года по еврейскому календарю, или некоторыми другими вещами во многих других календарях, которые поддерживают iOS и MacOS. ;

3) в свою очередь Calendar изменяет не только значения, возвращаемые в DateComponents, которые мы должны использовать для распаковки Date + Calendar в дни, месяцы, годы и эры (например, до н.э./н.э.), или даже номер недели и т.д... , а также некоторые календари могут иметь не те же компоненты, что и другие;

4) время суток (как вы знаете) зависит от TimeZone, так что одно и то же абсолютное время может быть одним из множества разных часов в зависимости от того, где вы находитесь. Он также может (как вы можете видеть в примере ниже) изменить дату, а также «часы». Это, конечно, может быть автоматическим (там, где вы находитесь) или заданным программистом;

5) кроме того, у нас есть DateFormatter (это удобно, которое оборачивает DateComponents), потому что 13 ноября 2017 года может быть представлено как 13/11/17 или 13/13/17 в зависимости от того, являетесь ли вы британцем. или американский. Мы также можем выбрать, будем ли мы использовать текстовый или числовой формат месяцев, и, если время отображается, в 12-часовом или 24-часовом формате - все это охватывается DateFormatter, но текстовое представление может быть «13e Novembre 2017», если вы француз, что вводит понятие

6) Locale, который может быть установлен, как и TimeZone, по умолчанию (как выбрано при настройке устройства) или указан программистом.

Код, который вы разместили, не будет работать, потому что все, что он делает, это берет Date, преобразует его через Calendar в DateComponents (пока все хорошо), но затем воссоздает Date из компонентов - все, что вы получите, это исходное Date - один и тот же абсолютный момент времени.

Что я считаю из вопроса и ваших ответов на вопросы в комментариях, так это то, что вам нужна функция, которая принимает абсолютное время (например, «сейчас»), также известное как Date, и отображает его в определенном TimeZone. Это работает:

func timeComponents(date: Date, timeZone: TimeZone) -> DateComponents {
    var calendar = Calendar.current
    calendar.timeZone = timeZone
    return calendar.dateComponents([.hour, .minute, .month, .year, .day, .second, .weekOfMonth], from: date)
}

let absTime: Date = Date() // Now
let edinburgh = TimeZone(abbreviation: "GMT")!
let newYork = TimeZone(abbreviation: "EST")!
let ec = timeComponents(date: absTime, timeZone: edinburgh)
let nycc = timeComponents(date: absTime, timeZone: newYork)
print(ec)// year: 2017 month: 11 day: 14 hour: 0 minute: 44 second: 10 weekOfMonth: 3 isLeapMonth: false 
print(nycc) // year: 2017 month: 11 day: 13 hour: 19 minute: 44 second: 10 weekOfMonth: 3 isLeapMonth: false 

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

func timeString(date: Date, timeZone: TimeZone, timeStyle: DateFormatter.Style) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.timeZone = timeZone
    dateFormatter.dateStyle = .none
    dateFormatter.timeStyle = timeStyle
    return dateFormatter.string(from: date)
}

let es = timeString(date: absTime, timeZone: edinburgh, timeStyle: .full)
let nycs = timeString(date: absTime, timeZone: newYork, timeStyle: .full)
print(es) // 12:44:10 AM Greenwich Mean Time
print(nycs) // 7:44:10 PM Eastern Standard Time

Вы можете продолжить и начать использовать Locale, если хотите интернационализировать свое приложение, но я оставлю это в качестве упражнения!

p.s. Это не все понятия — см. здесь

p.p.s. См. также этот ответ и этот ответ (ни дубликатов)

14.11.2017
  • Тема намного глубже, чем я себе представлял. 18.08.2020

  • 2

    Если вы просто хотите отформатировать дату в виде строки, рассмотрите возможность использования вместо нее DateFormatter:

    let date = Date()
    let formatter = DateFormatter()
    formatter.timeZone = TimeZone(identifier: "America/New_York")
    formatter.dateStyle = .long
    formatter.timeStyle = .long
    formatter.string(from: date)
    

    Если вы хотите получить компоненты даты и обработать их, используйте dateComponents(in:from:) метод.

    let components = Calendar.current.dateComponents(in: TimeZone(identifier: "America/New_York")!, from: date)
    
    13.11.2017
  • Я использовал components, но снова получил местную дату. Должен ли я определить и инициализировать что-то еще? 13.11.2017
  • @winnervswinner Вы создали новый Date, используя components? Это не сработает, потому что Date не содержит никакой информации о часовом поясе. Он представляет момент времени, независимо от того, где вы находитесь на земле. 13.11.2017
  • Итак, как я могу добавить другую дату. это то, за что я борюсь. 13.11.2017
  • Вы можете отобразить (отформатировать) дату для пользователя, используя первый фрагмент кода. Или, если вы хотите выполнить некоторые вычисления с компонентами, используйте второй фрагмент кода. Я не знаю, какова ваша конечная цель, потому что создание Date, представляющего момент времени в определенном часовом поясе, не имеет смысла, поскольку Date не представляет часовой пояс. @winnervswinner 13.11.2017
  • Я думаю, вы меня неправильно поняли. Я хочу показать людям разное время и даты из разных городов, а не их местные. Это то, что я пытаюсь сделать. 13.11.2017
  • @winnervswinner Хорошо, тогда используйте первый фрагмент кода. 13.11.2017

  • 3

    Если вы не знаете часовой пояс места, которое вы ищете, вы можете использовать CLGeocoder CoreLocation и выполнить поиск по строке адреса. Затем вы можете получить часовой пояс для этого места и перевести его во время, которое вы ищете:

    let geocoder = CLGeocoder()
    geocoder.geocodeAddressString("New York, New York") { (placemarks, error) in
        guard error == nil else {
            print("Error")
            print(error!.localizedDescription)
            return
        }
        guard let placemarks = placemarks,
            let place = placemarks.first else {
            print("No results")
            return
        }
    
        if let timeZone = place.timeZone {
            print("TimeZone: \(timeZone.identifier)")
            // TimeZone: America/New_York
    
            //Ignore the time zone offset from this one, it will be the difference between the current time and the new york time
            let dateInNewYork = Date().addingTimeInterval(TimeInterval.init(timeZone.secondsFromGMT()))
            print(dateInNewYork)
            // 2017-11-13 15:03:05 +0000
    
            //Or
            let formatter = DateFormatter()
            formatter.timeZone = TimeZone(identifier: timeZone.identifier)
            formatter.dateStyle = .long
            formatter.timeStyle = .long
            let formattedDateInNewYork = formatter.string(from: Date())
            print(formattedDateInNewYork)
            // November 13, 2017 at 3:03:05 PM EST
    
            //Or
            let components = Calendar.current.dateComponents(in: TimeZone(identifier: timeZone.identifier)!, from: Date())
            print(components.date!)
            // 2017-11-13 20:03:05 +0000
        }
    
    }
    
    13.11.2017
  • Мне не нужно получать местоположение людей, потому что я просто хочу показать людям даты и время в конкретных местах. Я все равно попробовал ваш код с точным адресом, но у меня не получилось. 13.11.2017
  • Это проверенный, рабочий код. Что в нем не сработало? Вы можете искать города, это не обязательно должны быть конкретные адреса. 13.11.2017
  • Я набрал Нью-Йорк, Нью-Йорк, Соединенные Штаты, а также попробовал ваши, но это дало мне мои местные даты. можешь поделиться со мной своими результатами? 13.11.2017
  • ibb.co/gy64Hb, как вы можете видеть по ссылке, я получаю те же данные. Я больше ничего не делал. это тот же код и его результат. 13.11.2017
  • В каком часовом поясе вы находитесь? 13.11.2017
  • Европа GMT+03:00 13.11.2017
  • Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

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


    Для любых предложений по сайту: [email protected]