How Does One Use Nsdateformatter's Islenient Option

iOS - NSDateFormatter dateFromString returns nil only in one case

After a few comments, it has been determined that the code in the question is being run with the locale of es_PE. This is the country of Peru. The date in question is January 1, 1990. By default, NSDateFormatter uses the local timezone and when parsing date strings that have no time, midnight is assumed.

In Peru, in the year 1990, day light savings began at midnight, January 1st, 1990. This means that clocks went from December 31, 1989 at 11:59:59pm straight to January 1, 1990 at 1:00:00am. There was no midnight on January 1, 1990.

This is why the attempt to convert the string 01-01-1990 failed for this user. There was no midnight for this date in Peru (and possibly a few other locales, if any, that had day light saving start at the same time). Most people testing this code would claim it works just fine since most people testing this code don't live in Peru.

I found a useful website with helpful information. See http://www.timeanddate.com/time/change/peru/lima?year=1990 for details about Peru and day light savings time. Note that in 1989 and 1991, Peru did not use day light savings time.

Convert string with unknown format (any format) to date

Xcode 11.4 • Swift 5.2 or later

You can use NSDataDetector as follow:

extension String {
var nsString: NSString { self as NSString }
var length: Int { nsString.length }
var nsRange: NSRange { .init(location: 0, length: length) }
var detectDates: [Date]? {
try? NSDataDetector(types: NSTextCheckingResult.CheckingType.date.rawValue)
.matches(in: self, range: nsRange)
.compactMap(\.date)
}
}


extension Collection where Iterator.Element == String {
var dates: [Date] { compactMap(\.detectDates).flatMap{$0}
}
}

Testing:

let dateStrings = ["January 3, 1966","Jan 3, 1966", "3 Jan 1966"]
for dateString in dateStrings {
if let dateDetected = dateString.detectDates?.first {
print(dateDetected)
// 1966-01-03 14:00:00 +0000
// 1966-01-03 14:00:00 +0000
// 1966-01-03 14:00:00 +0000
}
}

let dateStrings = ["January 3, 1966","Jan 3, 1966", "3 Jan 1966"]

for date in dateStrings.dates {
print(date)
// 1966-01-03 14:00:00 +0000
// 1966-01-03 14:00:00 +0000
// 1966-01-03 14:00:00 +0000
}

How to fix date formatter after adding 30 days to date

There are many issues here and lots of unnecessary code.

  1. Use the special en_US_POSIX locale when parsing a date string using a fixed format.
  2. You don't need stringFromThityDaysBefore. Your thirtyDaysBeforeToday is already a Date 30 days after endingDate.
  3. Don't set both the dateFormat and date/timeStyle of a date formatter. Only set one or the other.
  4. At the end, you want a new string representing the new date that is 30 days later. Your code fails because you convert a Date to a String using string interpolation and then you try to parse that string with your 2nd date formatter.

Here's the fixed code:

let timeStarting = "10:50"
let dateStarting = "03/10/2016"
let dateFormater = DateFormatter()
dateFormater.dateFormat = "dd/MM/yyyy HH:mm"
dateFormater.locale = Locale(identifier: "en_US_POSIX")
let timeAndDate = "\(dateStarting) \(timeStarting)"
let endingDate = dateFormater.date(from: timeAndDate)!

//ADD 30 DAYS TO ENDING DATE
let numberOfDays = 30
let thirtyDaysAfter = Calendar.current.date(byAdding: .day, value: numberOfDays, to: endingDate)!

//FORMAT AGAIN TO SHOW THE DATE IN AS (EX.: 13.10.2016)
let dateFormater2 = DateFormatter()
dateFormater2.dateFormat = "dd.MM.yy"
let newDateString = dateFormater2.string(from: thirtyDaysAfter)

The gives the result of 02.11.16 for newDateString.

One last thing to consider - don't use a dateFormat on the 2nd date formatter. Use date/timeStyle. It's always best to use a style for any date you wish to display to the user. This ensures it is formatted best for the user's locale.

Swift : How to convert String to string with time format?

You need 2 NSDateFormatters, one for dateFromString, one for stringFromDate

let inFormatter = NSDateFormatter()
inFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
inFormatter.dateFormat = "HH:mm"

let outFormatter = NSDateFormatter()
outFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
outFormatter.dateFormat = "hh:mm"

let inStr = "16:50"
let date = inFormatter.dateFromString(inStr)!
let outStr = outFormatter.stringFromDate(date)
println(outStr) // -> outputs 04:50

Swift 5

let inFormatter = DateFormatter()
inFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale
inFormatter.dateFormat = "hh:mm:ssa"

let outFormatter = DateFormatter()
outFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale
outFormatter.dateFormat = "hh:mm a"

let inStr = "16:50"
let datess = inFormatter.date(from: inStr)!
let outStr = outFormatter.string(from: datess)
print(outstr)


Related Topics



Leave a reply



Submit