web-dev-qa-db-ja.com

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) 

ここで検索しましたが、欲しいものが見つからず、日付ライブラリを探しています。私をリダイレクトするためのソースやサンプルを知っているなら、本当に感謝しています。

5
jorjj

日付を文字列にフォーマットするだけの場合は、代わりに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)
_
6
Sweeper

ここにはいくつかの異なる概念が関係しており、これを正しく行うには、(ほぼ)すべてを理解する必要があります...

1)Date(SwiftではNSDate)は絶対的な時点です-2017年11月13日のような実際の日付とは関係がないため、名前を少し間違えています。これを定義する必要があるためです。 ..

2)Calendar。グレゴリオ暦西部の2017年11月13日は、イスラム暦のサファル1439年、ヘシボン暦のヘシボン5778年の24日、またはiOSとMacOSがサポートする他の多くの暦のその他のことである可能性があるためです。 ;

3)次に、Calendarは、DateComponentsに返される値だけでなく、Date + Calendarを日、月、年、時代(BC/ADなど)、さらには週番号などに解凍するために使用する必要があります。 、だけでなく一部のカレンダーには他のカレンダーと同じコンポーネントがない場合があります;

4)時刻(ご存知のとおり)はTimeZoneに依存するため、同じabsolute時刻は、現在地に応じて「時」のさまざまな時刻の1つになる可能性があります。また、(以下の例でわかるように)dateと「時」を変更する場合もあります。もちろん、これは自動(現在の場所)でも、プログラマーが設定することもできます。

5)さらに、2017年11月13日couldは、英国人かどうかに応じて13/11/17または11/13/17として表されるため、DateFormatterDateComponentsをまとめるのに便利です)があります。またはアメリカ人。また、テキストと月のどちらを使用するか、時間を表示する場合は12時間形式と24時間形式のどちらを使用するかを選択することもできます。これらはすべて、DateFormatterでカバーされますが、butテキスト表現は次のようになります。フランス語の場合は「13eNovembre2017」の概念を紹介します

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.これらはnotすべての概念です ここ を参照してください

p.p.s. この回答 および この回答 (どちらも重複していない)も参照してください。

3
Grimxn

検索する場所のタイムゾーンがわからない場合は、CoreLocationのCLGeocoderを使用して、住所文字列を検索できます。次に、その場所のタイムゾーンを取得し、それを探している時間に変換できます。

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
    }

}
2
Zig