0

I'm having trouble reformatting a date to only show .year .monthand .day. The output prints are the same string I input but with hourand minutesshowing zeros and my goal is to only have a string "yyyy-MM-dd"as i'l use it to fetch CoreData for records. If I use that date format Xcode crashes because the incoming date format is "yyyy-MM-dd HH:mm:ssZZZZ". I followed suggested solution from Convert string to date in Swift but is not working in may case. How can a reformat the date? As always thank you very much. Here is the function :

func fetchBookings(date : String ) {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ssZZZZ"
//        dateFormatter.dateFormat = "yyyy-MM-dd"
        let dateFormatted = dateFormatter.date(from:date)!

        let calendar = Calendar.current
        let components = (calendar as NSCalendar).components([.year, .month,.day] , from: dateFormatted)
        let dateToCheck = calendar.date(from: components)
        let context =  CoreData.databaseContext
        let fetchRequest = NSFetchRequest<Booking>(entityName: "Booking")
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "bookingDate", ascending: true)]

        let userPredicate = NSPredicate(format: "user.name == %@", UserDetails.fullName ?? "")
        let datePredicate = NSPredicate(format: "bookingDate CONTAINS %@", dateToCheck! as CVarArg)
        let andPredicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.and, subpredicates: [userPredicate, datePredicate])
        fetchRequest.predicate = andPredicate
        fetchedResultController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
        do {
            try fetchedResultController.performFetch()
            print("##################### selectedDate in fetchBooking() is :\(self.selectedDate) ")
            print(" bookings fetched")
            print("booking date is: \(date)")
            print("dateTocheck is: \(String(describing: dateToCheck!))")
            print("today date is : \(Date())")
            print("fetched objects are: \(String(describing: fetchedResultController.fetchedObjects))")
        } catch  {
            print("Error fetching bookings :\(error)" )
        }
    }
vadian
  • 274,689
  • 30
  • 353
  • 361
Vincenzo
  • 5,304
  • 5
  • 38
  • 96
  • 1
    Just parse the date, change the date formatter as you commented out `dateFormatter.dateFormat = "yyyy-MM-dd"`and format the parsed date again – Leo Dabus May 13 '19 at 12:28
  • Be aware that CONTAINS doesn’t work with dates. You have to use BETWEEN with two arguments or two comparisons `>= start && < end`. – vadian May 13 '19 at 12:35
  • @vadian using `CONTAINS`wouldn't work with a `String` from `dateToCheck`? – Vincenzo May 13 '19 at 12:39
  • No, it wouldn’t. CONTAINS checks for a substring in a string but not for a date in a date range. – vadian May 13 '19 at 12:42
  • @vadian writing the date predicate as `let datePredicate = NSPredicate(format: "bookingDate >= start && < end %@", dateToCheck` is giving me this: `Thread 1: breakpoint 1.1 2.1`, and in console I get `Unable to parse the format string "bookingDate >= start && < end %@"`. I should I do two different predicates I guess. Also, I save dates in `CoreData`as strings, that's why I thought of `CONTAINS` – Vincenzo May 13 '19 at 12:53
  • @vadian I ended up using `BEGINSWITH` and it fetches the right one. Thanks – Vincenzo May 13 '19 at 13:10

3 Answers3

1

Simply create a String extension and

1. convert String to Date with format yyyy-MM-dd HH:mm:ssZZZZ

2. convert Date to String with format yyyy-MM-dd

extension String {
    var formattedDate: String? {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ssZZZZ"
        if let date = dateFormatter.date(from: self) {
            print(date)
            dateFormatter.dateFormat = "yyyy-MM-dd"
            return dateFormatter.string(from: date)
        }
        return nil
    }
}

Example:

let dateStr = "2017-04-10 10:33:42GMT"
let formattedDate = dateStr.formattedDate //Output: "2017-04-10"
PGDev
  • 23,751
  • 6
  • 34
  • 88
  • i tried just reformatting the date again as Leo Dabus suggested. Maybe a quick and fast solution as extension to `String`may be overkill, but thanks for another higher lever class. I'll accept your answer anyway as basically that's the code I used. Thanks. – Vincenzo May 13 '19 at 13:21
0
func getDateWithoutTime(string: String) -> String? {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ssZZZZ"
    if let date = dateFormatter.date(from: string) {
        dateFormatter.dateFormat = "yyyy-MM-dd"
        return dateFormatter.string(from: date)
    }
    return nil
}
print(getDateWithoutTime1(string:"2019-05-13 12:27:53GMT"))   

2019-05-13

RajeshKumar R
  • 15,445
  • 2
  • 38
  • 70
0

Use the below function where you pass the date, the current date format and the required date format.

let dateStr = self.convertDateFormaterCommon(currentFormat: "yyyy-MM-dd HH:mm:ss", reqdFormat: "dd MMM, yyyy", dateStr: myObj.transferDate ?? "")

func convertDateFormaterCommon(currentFormat:String, reqdFormat:String, dateStr: String) -> String
{
    if dateStr != ""{
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = currentFormat
        dateFormatter.locale = Locale(identifier: "en_US")
        let date = dateFormatter.date(from: dateStr)
        dateFormatter.dateFormat = reqdFormat
        return  dateFormatter.string(from: date ?? Date())
    }
    return ""
}
Yogesh Tandel
  • 1,738
  • 1
  • 19
  • 25