Problem converting a string to a Date Object - swift

I have a DatePicker View, When the user clicks a UITextField, it show the DatePicker, which the user can of course, pick a date.
The problem is, when I'm trying to convert the String, to be a date object, I get nothing, so I cannot compare two dates for example.
func checkDate(){
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: Locale.current.identifier)
dateFormatter.timeZone = .current
dateFormatter.dateFormat = "dd/MM/yy"
guard let startDate = mView.startDateTextField.text else { return }
print("DATE: \(startDate)")
guard let startDateFromString = dateFormatter.date(from: startDate) else { return } //I think it returns here.
//Won't get here.
print("DATE: \(startDate)")
guard let endDate = mView.endDateTextField.text else { return }
guard let endDateFromString = dateFormatter.date(from: endDate) else { return }
if startDateFromString.compare(endDateFromString) == ComparisonResult.orderedDescending{
print("Start date cannot be greater than end date.")
}
}
I tried to debug, and the break point does gets to startDateFromString line, but from theres "jumps" outside, so I guess it won't get the Date from the string and returns.
I just can't figure out why.
EDIT: This is where I set the TextField Text to be the date chosen from the DatePicker.
#objc func datePickerValueChanged(sender: UIDatePicker){
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateTextField.text = dateFormatter.string(from: sender.date)
}

Maybe you are using wrong dateFormat. Check your dateFormat from here
For example if your dateString is "Mar 1, 2019", you have to use it as dateFormat "MMM d, yyyy"
dateFormatter.dateFormat = "MMM d, yyyy"

Related

How can I show month and year in 12's timezone in swift?

func getMonYearDateFormat() -> String {
let dateFormatter = DateFormatter()//EEEE, d, MMM
dateFormatter.dateFormat = is24Hour() ? "yyyy-MM-dd' 'HH:mm:ss" : "yyyy-MM-dd' 'h:mm:ss a"
dateFormatter.timeZone = TimeZone.current
dateFormatter.locale = Locale.current
guard let oldDate = dateFormatter.date(from: self) else { return "" }
let convertDateFormatter = DateFormatter()
convertDateFormatter.dateFormat = "MMMM yyyy"
return convertDateFormatter.string(from: oldDate)
}
I show month and year as title in table view. I wrote this function to convert the date of the relevant card to month and year. If the device is in the 24-hour time zone, the function works properly. However, if the device is in the 12th time zone, it returns blank and I cannot see the month and year of the relevant card. I couldn't find the part that I wrote incorrectly in the function.
I've tested your code with 12 hour format and it works. The only thing I've. change is to use the 12 hour format without call is24Hour() because you did not provide that code. So I suspect the point of failure is the is24Hour() function.
As mentioned in the comments I would recommend you to investigate how you get this string and if possibly use the original Date object instead if it exists but below is a solution that I think handles the 12 vs 24h issue in an efficient way.
The logic is to first convert using 24h and if that returns nil then convert using the 12h format.
I have declared all formatters I use as static properties so they only get created one since creating a DateFormatter is expensive
extension String {
private static let formatter24: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ss"
return dateFormatter
}()
private static let formatter12: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd' 'h:mm:ss a"
return dateFormatter
}()
private static let formatterMonthYear: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM yyyy"
return dateFormatter
}()
func getMonYearDateFormat() -> String {
let date = Self.formatter24.date(from: self) ?? Self.formatter12.date(from: self)
guard let date else { return "" }
return Self.formatterMonthYear.string(from: date)
}
}

Compare current system date with another date(which is coming as string format 2019-11-22) in swift

I'm getting date as a sting format from API (2019-11-22), I want to compare this date with current date.
I tried converting current date as string format this is success but this is not satisfying requiremet. I have to convert to String(2019-11-22) to Date and then I can compare two dates.
How can I convert string (2019-11-22) to Date to compare with system date pls help I'm lead knowledge in dates. Thanks in advance.
extension Date {
static func getCurrentDate() -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
return dateFormatter.string(from: Date())
}
}
if Date() < apiEach["ExpiryDate"]! as! Date{
//apiEach["ExpiryDate"]! is 2019-11-22
pritn("You can proceed it's not outdated")
}
apiEach["ExpiryDate"] is a string (apiEach["ExpiryDate"] as! Date will crash) so you have two options:
Convert the current date to string
if Date.getCurrentDate() < apiEach["ExpiryDate"] as! String { ...
Convert the API string to Date and compare that
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd"
if let apiDate = dateFormatter.date(from: apiEach["ExpiryDate"] as! String),
Date() < apiDate { ...
func minimumDate(result:String) -> Bool {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let myDate = dateFormatter.date(from: "\(result)")
dateFormatter.dateFormat = "yyyy-MM-dd"
let now = Date()
let startDateComparisionResult:ComparisonResult = now.compare(myDate!)
if startDateComparisionResult == ComparisonResult.orderedAscending {
print("Current date is smaller than end date.")
let somedateString = dateFormatter.string(from: myDate!)
print(somedateString)
return true
}
else if startDateComparisionResult == ComparisonResult.orderedDescending {
// Current date is greater than end date.
print("Current date is greater than end date.")
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date1String = dateFormatter.string(from: myDate!)
let date2String = dateFormatter.string(from: now)
if date1String == date2String {
print("Equal date")
return true
}
return false
}
else if startDateComparisionResult == ComparisonResult.orderedSame {
// Current date and end date are same
print("Current date and end date are same")
return true
}
return true
}
Since the date format "yyyy-MM-dd" can be properly sorted/compared you can either convert current date to a string and compare it with your API value
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let now = dateFormatter.string(from: Date())
switch now.compare(input) { //input is from API
case .orderedSame:
print("Same")
case .orderedAscending:
print("Before")
case .orderedDescending:
print("After")
}
If you want to compare dates it is important that Date() will also include the current time while a date converted using a date formatter with a date only format will have its time zeroed out (midnight) so the comparison might not be correct if the date part is the same. To handle this it is better to use DateComponents
let calendar = Calendar.current
guard let date = dateFormatter.date(from: input) else { return //or error }
let components = calendar.dateComponents([.year, .month, .day], from: now, to: date)
if let year = components.year, let month = components.month, let day = components.day {
switch (year + month + day) {
case 0: // all values are zero
print("Same")
case ..<0 : // values will be zero or negative so sum is negative
print("After")
default: // values will be zero or positive so sum is positive
print("Before")
}
}

How to convert this string in a date with this format?

Im working with a API, when I ask for a date, this API get my a String like this:
20190717-0300
I want to show that date in a UILabel with this format: "dd '\(preposition)' MMMM"
My attempt was to make a string extension:
extension String {
var toDate: String? {
let dateFormatter = DateFormatter()
let preposition = NSLocalizedString("of", comment: "Preposition of dates formatted")
dateFormatter.dateFormat = "dd '\(preposition)' MMMM"
dateFormatter.locale = Locale.current
if let date = dateFormatter.date(from: self) {
let dateString = dateFormatter.string(from: date)
return dateString
}
return nil
}
}
And then use it:
myLabel.text = thatString.toDate
But .toDate always return nil
Note: The answers I found on the site are cases with ISO format strings.
Expected result:
17 of July
Basically you need an input date format and an output date format.
extension String {
var toDate: String? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMddZ"
if let date = dateFormatter.date(from: self) {
let preposition = NSLocalizedString("of", comment: "Preposition of dates formatted")
dateFormatter.dateFormat = "dd '\(preposition)' MMMM"
let dateString = dateFormatter.string(from: date)
return dateString
}
return nil
}
}
I totally agree with rmaddy's comment to use setLocalizedDateFormatFromTemplate
The source of the date field symbols is unicode.org: Date Format Patterns
Turn this into extension if you like:
// function
func formatDate(_ from:String, preposition:String) -> String? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMddZ"
guard let date = dateFormatter.date(from: from) else {
return nil
}
dateFormatter.dateFormat = "dd '\(preposition)' MMMM"
return dateFormatter.string(from: date)
}
// example usage
let str = "20190717-0300"
if let formatted = formatDate(str, preposition: "of") {
print(formatted)
}

swift 4 Date from from ISO string to custom format?

I have ISO date from API I want to convert it to another custom date format, I've checked some threads here it's look like I have to use the extension on Date class, unfortunately, all my attempts failed.
this example for date i have :
2014-10-22T00:00:00+00:00
I want to convert it to July 2014
can I use normal Date class to do it?
and below what I am trying to do
let formatter = ISO8601DateFormatter()
let date = formatter.date(from: "2016-08-26T12:39:00Z")
let string = formatter.string(from: Date())
Try it:
let formatter = ISO8601DateFormatter()
if let date = formatter.date(from: "2014-10-22T00:00:00+00:00") {
let string = date.stringDate
print(string) // October 2014
}
extension Date {
var stringDate: String {
let formatter = DateFormatter()
formatter.dateFormat = "MMMM yyyy"
return formatter.string(from: self)
}
}
my Date load from SQL Server and format like this "2018-01-17T03:08:28.158769" the code below is work for me perfectly
let isoDate = "2018-01-17T03:08:28.158769"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS"
let date = dateFormatter.date(from:isoDate!)!
dateFormatter.dateFormat = "d.MMMM.YYYY"
let displayDate = dateFormatter.string(from: date)
displayDateInLabel.text = displayDate
result
17.January.2018
You can get Month and Year like this
override func viewDidLoad() {
super.viewDidLoad()
print(getFormattedDate(date: Date()))
}
func getFormattedDate(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM YYYY"
let strMonth = dateFormatter.string(from: date)
return strMonth
}

NSDateFormatter. Setting time elapsed since date in swift

I'm looking to call a function that checks time elapsed since date. This will determine how the timeLable displays in my messages view controller, similar to IMessage.
The code I'm using below only shows HH:MM
let date = dateFormatter().dateFromString((recent["date"] as? String)!)
timeLabel.text = NSDateFormatter.localizedStringFromDate(date!, dateStyle: NSDateFormatterStyle.NoStyle, timeStyle: NSDateFormatterStyle.NoStyle)
I'm looking to change it to something along the lines of:
If date is today, date = "HH:MM"
If date is Yesterday, date = "Yesterday"
If date is the day before yesterday and so on, date = "Monday, Tuesday, Wednesday..."
If date is over 1 week, date = MM/DD/YY
Or try this. Note that we have to use components:fromDate: and then use components:fromDateComponents:toDateComponents:options: because if we don't 23:59 last night returns 23:59 instead of Yesterday.
extension NSDateFormatter {
static func friendlyStringForDate(date:NSDate) -> String {
// Fetch the default calendar
let calendar = NSCalendar.currentCalendar()
// Compute components from target date
let from = calendar.components([.Day, .Month, .Year], fromDate: date)
// Compute components from current date
let to = calendar.components([.Day, .Month, .Year], fromDate: NSDate())
// Compute days difference between the two
let delta = calendar.components(.Day, fromDateComponents: from, toDateComponents: to, options: [])
switch delta.day {
case 0:
let formatter = NSDateFormatter()
formatter.timeZone = NSTimeZone.defaultTimeZone()
formatter.dateFormat = "HH:mm"
return formatter.stringFromDate(date)
case 1:
return "Yesterday"
case 2..<7:
let formatter = NSDateFormatter()
formatter.timeStyle = .NoStyle
formatter.dateFormat = "EEEE"
return formatter.stringFromDate(date)
default:
let formatter = NSDateFormatter()
formatter.timeStyle = .NoStyle
formatter.dateFormat = "MM/dd/YY"
return formatter.stringFromDate(date)
}
}
}
Now then, to use it just:
timeLabel.text = NSDateFormatter.friendlyStringForDate(date!)
SWIFT 3:
extension DateFormatter {
static func friendlyStringForDate(date: Date) -> String {
// Fetch the default calendar
let calendar = Calendar.current
let unitFlags: NSCalendar.Unit = [.day]
// Compute days difference between the two
let delta = (calendar as NSCalendar).components(unitFlags, from: date, to: Date(), options: [])
if let day = delta.day {
switch day {
case 0:
let formatter = DateFormatter()
formatter.timeZone = NSTimeZone.default
formatter.dateFormat = "hh:mm a"
return formatter.string(from: date)
case 1:
return "Yesterday"
case 2..<7:
let formatter = DateFormatter()
formatter.timeStyle = .none
formatter.dateFormat = "EEEE"
return formatter.string(from: date)
default:
let formatter = DateFormatter()
formatter.timeStyle = .none
formatter.dateFormat = "MM/dd/YY"
return formatter.string(from: date)
}
}
return ""
}
}