0

I'm testing some values for a date format ("dd-MM-yyyy") and there's a special case that I can't explain:

var datef = NSDateFormatter()
datef.dateFormat = "dd-MM-yyyy";
var date_a = "02-01-1990"
var date_b = "01-01-1990"
var date_f_a = datef.dateFromString(date_a);
var date_f_b = datef.dateFromString(date_b);

data_f_a returns Jan 2, 1990, 12:00 AM, but date_f_b returns nil. Any other date will return the expected value, except for January 1st, 1990.

If I add datef.lenient = true date_f_b is no longer nil, but I shouldn't need to do that. Why is it an invalid date?

EDIT 1: It happens the same if I use DateFormatter():

Using Swift version 3

EDIT 2: Xcode version: 8.1

Yogendra Girase
  • 631
  • 3
  • 15
Gio MV
  • 105
  • 1
  • 8

2 Answers2

3

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.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
0

For xCode 7.3 You need to use NSDateComponents

var datef = NSDateFormatter()
datef.dateFormat = "dd-MM-yyyy";

var dtCompo = NSDateComponents()
dtCompo.day = 2
dtCompo.month = 1
dtCompo.year = 1990
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
var date_f_a = cal.dateFromComponents(dtCompo)

dtCompo = NSDateComponents()
dtCompo.day = 1
dtCompo.month = 1
dtCompo.year = 1990
var date_f_b = cal.dateFromComponents(dtCompo)

var date_f_a_string = datef.stringFromDate(date_f_a!)
var date_f_b_string = datef.stringFromDate(date_f_b!)

print(date_f_a_string)
print(date_f_b_string)

Output will enter image description here xCode 8.1

var datef = DateFormatter()
datef.dateFormat = "dd-MM-yyyy";

var dtCompo = DateComponents()
dtCompo.day = 2
dtCompo.month = 1
dtCompo.year = 1990
let cal = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)!
var date_f_a = cal.date(from: dtCompo)

dtCompo = DateComponents()
dtCompo.day = 1
dtCompo.month = 1
dtCompo.year = 1990
var date_f_b = cal.date(from: dtCompo)

var date_f_a_string = datef.string(from: date_f_a!)
var date_f_b_string = datef.string(from: date_f_b!)

print(date_f_a_string)
print(date_f_b_string)

Output will enter image description here

jignesh Vadadoriya
  • 3,244
  • 3
  • 18
  • 29
  • I'm using `NSDateFormatter` because of my swift version (2.2). – Gio MV Dec 07 '16 at 05:03
  • With the latest version, I'm having the same issue – Gio MV Dec 07 '16 at 05:04
  • i have two xCode and both will give proper out put as per my updated answer – jignesh Vadadoriya Dec 07 '16 at 05:18
  • What's your time zone? – Gio MV Dec 07 '16 at 05:22
  • 1
    IST time zone +5:30 – jignesh Vadadoriya Dec 07 '16 at 05:27
  • Wow, if I change my timezone, it seems to work, but in my current location (Lima, Peru) I get nil. If you try changing your Time Zone in the mac settings for Date & Time and set it to Lima, Peru, you should see nil. – Gio MV Dec 07 '16 at 05:33
  • It seems that in my country, on that specific date, daylight saving time was applied, so it doesn't exist that hour (between 12:00 am and 1:00 am, on Jan 1, 1990). – Gio MV Dec 07 '16 at 05:39
  • OMG, give me some time i will check that – jignesh Vadadoriya Dec 07 '16 at 05:41
  • i have fingureout this issue with your timezone – jignesh Vadadoriya Dec 07 '16 at 07:13
  • Using DateComponents removes the nil result, however I'm receiving an NSString as date input, with the format "dd-MM-yyyy", and I'll need to parse each component if I want to build each date component. If I want to avoid that, I just need to use `datef.leniant = true`. Good thing is that I now understand the real issue. – Gio MV Dec 07 '16 at 14:40
  • The posted answer is just some code. It makes no attempt to actually answer the question. Please update this answer to explain what the actual issue was and explain how the posted code solves the problem (since it does not). – rmaddy Dec 07 '16 at 16:46
  • @Gio MV if you are using 'datef.leniant = true' then you output date will not proper "If a formatter is set to be lenient, when parsing a string it uses heuristics to guess at the date which is intended. As with any guessing, it may get the result date wrong (that is, a date other than that which was intended)." you can refers this Question http://stackoverflow.com/questions/39730317/how-does-one-use-nsdateformatters-islenient-option – jignesh Vadadoriya Dec 08 '16 at 06:05