Search code examples
swiftswift3nsdatensdateformatter

How to fix date formatter after adding 30 days to date


I am getting date and time into different strings and getting them together in date format using date formatter. After this, I am adding 30 days to the resulted date. Now I am trying to use dateFormatter again but whatever I do it will result in nil (even though it's not nil). What am I doing wrong?

 //GET TIME AND DATE FROM TWO STRINGS
    var timeStarting = "10:50"
    var dateStarting = "03/10/2016"
    let date = Date()
    let timeStamp = NSDate().timeIntervalSince1970
    let dateFormater = DateFormatter()
    dateFormater.dateStyle = .short
    dateFormater.timeStyle = .none
    dateFormater.dateFormat = "dd/MM/yyyy HH:mm"
    var timeAndDate = "\(dateStarting) \(timeStarting)"
    let endingDate : Date = dateFormater.date(from: "\(timeAndDate)")!

    //ADD 30 DAYS TO ENDING DATE
    var numberOfDays = "30"
    let thirtyDaysBeforeToday = Calendar.current.date(byAdding: .day, value: Int(numberOfDays)!, to: endingDate)
    var stringFromThityDaysBefore : String = "\(thirtyDaysBeforeToday!)"

    //FORMAT AGAIN TO SHOW THE DATE IN AS (EX.: 13.10.2016)
    let dateFormater2 = DateFormatter()
    dateFormater2.isLenient = true
    dateFormater2.dateStyle = .short
    dateFormater2.timeStyle = .none
    dateFormater2.dateFormat = "dd.MM.yy"
    var newDates : Date = dateFormater2.date(from: "\(stringFromThityDaysBefore)")!

(RESULT EX.: 13.10.2016) - WITH 30 DAYS AFTER THE ENDING DATE


Solution

  • 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.