質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

1418閲覧

経過時刻を表示するための処理をextensionで拡張して使いたい

ZY.

総合スコア22

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2020/05/09 13:41

下記のように処理を書いてみましたが、5年以上前の記事を参考に書いてみたのですがうまくいかず。
取得するCalendarから必要なコンポーネントを取得しているところの処理でエラーが'Unit' is not a member type of 'Calendar'のエラーも発生してしまいます。
何か参考になるような書き方があれば教えていただけないでしょうか。

Swift

1import Foundation 2 3extension Date { 4 func toFuzzy() -> String { 5 6 // 現在時刻を取得する 7 let now = Date() 8 9 // カレンダーを作成する 10 let cal = Calendar.current 11 12 13 let calUnit: Calendar.Unit = .CalendarUnitSecond | .CalendarUnitMinute | .CalendarUnitHour | .CalendarUnitDay | .CalendarUnitYear 14 let components = cal.components(calUnit, fromDate: self, toDate: now, options: nil) 15 16 let diffSec = components.second + components.minute*60 + components.hour*3600 + components.day*86400 + components.year*31536000 17 var result = String() 18 19 if diffSec < 60 { 20 result = "(diffSec)秒前" 21 } else if diffSec < 3600 { 22 result = "(diffSec/60)分前" 23 } else if diffSec < 86400 { 24 result = "(diffSec/3600)時間前" 25 } else if diffSec < 2764800 { 26 result = "(diffSec/86400)日前" 27 } else { 28 let dateFormatter = DateFormatter() 29 30 if components.year > 0 { 31 dateFormatter.dateFormat = "yyyy年M月d日" 32 result = dateFormatter.string(from: self) 33 } else { 34 dateFormatter.dateFormat = "M月d日" 35 result = dateFormatter.string(from: self) 36 } 37 } 38 39 return result 40 } 41 42 static func parse(dateString:String) -> Date { 43 let formatter = DateFormatter() 44 formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZZZ" 45 let d = formatter.date(from: dateString) 46 return Date(timeInterval: 0, since: d!) 47 } 48} 49

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2020/05/09 17:11

あえて細かいツッコミどころをあげると、せっかく date components を取得したのに秒数に直すのは無駄な気がするとか、何かの手違い (サーバーと端末の時間がずれてるとか) で未来の日付を表示しようとしたらマイナスの秒数が表示されるとか、夏時間の切り替えとか、和暦の表示が微妙とか…。
TsukubaDepot

2020/05/10 22:17

ああ、確かにそうですね。かけて割っているので余計な手順を増やしているだけですね。それ以外の条件もかんげないといけないですが、考えたくないですね。
guest

回答1

0

ベストアンサー

とりあえず動くようにメソッド名などを書き換える、という程度であれば、次のような感じになります。
変更点はコメントをご参照ください。

swift

1import Foundation 2 3extension Date { 4 func toFuzzy() -> String { 5 6 // 現在時刻を取得する 7 let now = Date() 8 9 // カレンダーを作成する 10 let cal = Calendar.current 11 12 // MARK: メソッド名と引数の指定方法が変わっているので変更 13 //let calUnit: Calendar.Unit = .CalendarUnitSecond | .CalendarUnitMinute | .CalendarUnitHour | .CalendarUnitDay | .CalendarUnitYear 14 //let components = cal.components(calUnit, fromDate: self, toDate: now, options: nil) 15 let components = cal.dateComponents([.second, .minute, .hour, .day, .year], from: self, to: now) 16 17 // MARK: 各プロパティはオプショナル型として宣言されているため、強制アンラップを行なっている 18 // 目的などに応じて適切に書き換える必要がある 19 let diffSec = components.second! + components.minute! * 60 + components.hour! * 3600 + components.day! * 86400 + components.year! * 31536000 20 21 var result = String() 22 23 if diffSec < 60 { 24 result = "(diffSec)秒前" 25 } else if diffSec < 3600 { 26 result = "(diffSec/60)分前" 27 } else if diffSec < 86400 { 28 result = "(diffSec/3600)時間前" 29 } else if diffSec < 2764800 { 30 result = "(diffSec/86400)日前" 31 } else { 32 let dateFormatter = DateFormatter() 33 34 // MARK: year はオプショナル型のため強制アンラップを行なっている 35 if components.year! > 0 { 36 dateFormatter.dateFormat = "yyyy年M月d日" 37 result = dateFormatter.string(from: self) 38 } else { 39 dateFormatter.dateFormat = "M月d日" 40 result = dateFormatter.string(from: self) 41 } 42 } 43 44 return result 45 } 46 47 static func parse(dateString:String) -> Date { 48 let formatter = DateFormatter() 49 formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZZZ" 50 let d = formatter.date(from: dateString) 51 return Date(timeInterval: 0, since: d!) 52 } 53} 54 55// 以下は playground での検証用コード 56let d = Date() 57 58Thread.sleep(forTimeInterval: 25) 59 60print(d.toFuzzy())

コメントにも書いていますが、いくつかのプロパティがオプショナル型で宣言されています。
上記の修正では強制アンラップで処理していますが、当然該当する値が nil の場合は実行時エラーで強制終了してしまいますので、適切な方法に変更していただければと思います。

投稿2020/05/09 15:17

TsukubaDepot

総合スコア5086

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ZY.

2020/05/10 16:23

ご回答ありがとうございます。 こちらで対応させていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問