11

I want to show a date as Saturday June 13.

If the date is current day it should display Today like that Tomorrow, Yesterday.

I couldn't achieve both

guard let date = Date(fromString: "16 September 2020",
                      format: "dd MMMM yyyy") else { return nil }

        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .medium
        dateFormatter.doesRelativeDateFormatting = true

        header.titleLabel.text = dateFormatter.string(from: date)

For the above code I can show date as Today Tomorrow Yesterday but other dates are not showing Saturday June 13. I tried to apply date format dateFormatter.dateFormat = "EEEE, MMM d" for the same dateFormatter it returned nothing.

Anees
  • 514
  • 5
  • 20
  • The basic code seems to work find for me, 2 days ago show `14 Sep 2020`, 1 day ago shows `Yesterday`, today shows `Today`, 1 day in the future shows `Tomorrow` and 2 days in the future shows `18 Sep 2020` - I'd be more focus on you parser – MadProgrammer Sep 16 '20 at 07:23
  • Can you show the code for `Date.init(fromString:format:)`? – Sweeper Sep 16 '20 at 07:26

2 Answers2

23

The DateFormatter doesn't behave well when setting doesRelativeDateFormatting = true and trying to apply a custom format at the same time. So the easiest solution is to use the format given by a Style and a Locale

let relativeDateFormatter = DateFormatter()
relativeDateFormatter.timeStyle = .none
relativeDateFormatter.dateStyle = .medium
relativeDateFormatter.locale = Locale(identifier: "en_GB")
relativeDateFormatter.doesRelativeDateFormatting = true

Example

let inputFormatter = DateFormatter()
inputFormatter.dateFormat = "yyyy-MM-dd"

let dates = ["2020-09-01", "2020-09-15", "2020-09-16", "2020-09-30"].compactMap { inputFormatter.date(from: $0)}

for date in dates {
    print(relativeDateFormatter.string(from: date))
}

1 Sep 2020
Yesterday
Today
30 Sep 2020

Now if you want to apply a custom format I have not found a solution for this when using the same DateFormatter instance so we need to create a new one for the custom format and use it together with a check so we apply the custom format only when it is not Today etc

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE, MMM dd"

for date in dates {
    let string = relativeDateFormatter.string(from: date)
    if let _ = string.rangeOfCharacter(from: .decimalDigits) {
         print(dateFormatter.string(from: date))
    } else {
        print(string)
    }
}

Tuesday, Sep 01
Yesterday
Today
Wednesday, Sep 30

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
5

You can also use RelativeDateFormatter. Here is an example:

let date = Date().addingTimeInterval(-4 * 24 * 60 * 60)

let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .full

let relativeDate = formatter.localizedString(for: date, relativeTo: Date())

print(relativeDate) // 4 days ago
Hossam Ghareeb
  • 7,063
  • 3
  • 53
  • 64