Здесь задействовано несколько разных концепций, и нам нужно понять (почти) все из них, чтобы понять это правильно...
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