Help us understand the problem. What is going on with this article?

[Swift] Date生成時にありえない日付のときはnilを返したい

TL;DR

DateFormatterを使い isLenient = false に設定する。

func makeDate(year: Int, month: Int, day: Int) -> Date? {
    let formatter = DateFormatter()
    formatter.calendar = Calendar(identifier: .gregorian)
    formatter.timeZone = TimeZone(secondsFromGMT: 0)
    formatter.isLenient = false
    formatter.dateFormat = "yyyy-MM-dd"
    return formatter.date(from: String(format: "%d-%02d-%02d", year, month, day))
}

let date = makeDate(year: 2021, month: 2, day: 29)
// -> nil

やりたいこと

例えば年と月と日を別々に入力するUIがあってそこからDate型を生成したいとき、ユーザーが2021年2月29日のような存在しない日付を入力したらnilを返したい。

❌ DateComponentsを使う方法

func makeDate(year: Int, month: Int, day: Int) -> Date? {
    var components = DateComponents()
    components.calendar = Calendar(identifier: .gregorian)
    components.timeZone = TimeZone(secondsFromGMT: 0)
    components.year = year
    components.month = month
    components.day = day
    return components.date
}

let date = makeDate(year: 2021, month: 2, day: 29)
// -> 2021年3月1日

自動で日が進んで別の日付を返してしまう。

❌ DateFormatterを使ってisLenientを指定しない方法

func makeDate(year: Int, month: Int, day: Int) -> Date? {
    let formatter = DateFormatter()
    formatter.calendar = Calendar(identifier: .gregorian)
    formatter.timeZone = TimeZone(secondsFromGMT: 0)
    formatter.dateFormat = "yyyy-MM-dd"
    return formatter.date(from: String(format: "%d-%02d-%02d", year, month, day))
}

let date = makeDate(year: 2021, month: 2, day: 29)
// -> 2021年3月1日

自動で日が進んで別の日付を返してしまう。

ただし、32日を指定するとnilが返ってくる。
この挙動はDateComponentsとは異なる。

let date = makeDate(year: 2021, month: 2, day: 32)
// -> nil

環境

Swift 5.1

謝辞

@kishikawakatsumi さんに教えていただきました。ありがとうございました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした