0

I am trying to parse a list of dates. The dates look like this: "01MAY16, 01JUN16, 01AUG16" and so on. Up until now the dates have all been in english and I have successfully used the NSDateFormatter like this:

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "ddMMMyy"
dateFormatter.locale = NSLocale(localeIdentifier: "en_US")

let date = dateFormatter.dateFromString("01MAY16")

I have now stumbled upon an issue. The dates I parse have a tendency to be displayed with swedish locale like this: "01MAJ16, 01JUN16, 01OKT16". I was hoping this could be parsed by setting the locale in the dateformatter to swedish like this:

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "ddMMMyy"
dateFormatter.locale = NSLocale(localeIdentifier: "sv_SE")

let date = dateFormatter.dateFromString("01MAJ16")

This works fine when the date is 'MAJ', but only because that month is a 3-letter month. If I try the following the date returned is nil:

let date = dateFormatter.dateFromString("01JUN16")

It returns nil because the format it is looking for is apparently 'juni'. So the format MMM does not imply 3-letters.

So to my question. What is the easiest way to solve this? Is there a trick I can use or do I have to create my own formatter?

EDIT

I learned a lot of new things from you, thank you. Setting the shortMonthSymbols manually is a good solution, but in my case I would have to do that for both norwegian, swedish and danish locale. I came up with a solution that overrides the dateFromString() method of the NSDateFormatter. Please tell me if I have done something very stupid. This formatter is used when I know that all the dates I parse (any locale) always uses 3-letter month:

class CustomDateFormatter : NSDateFormatter {

override func dateFromString(string: String) -> NSDate? {

    guard let date = super.dateFromString(string) else {

        //I only override the dateFormatter if no date is found and the dateFormat is set to exactly 3 M's (i.e ddMMMyy)
        let charactersInDateFormat = self.dateFormat.characters

        let mChars = charactersInDateFormat.filter { $0 == "M" }

        guard mChars.count == 3 else {

            return nil
        }

        var modifiedDateString = string.lowercaseString

        for monthLocale in self.shortMonthSymbols {

            let index = monthLocale.startIndex.advancedBy(3)

            let threeLetterMonthString = monthLocale.substringToIndex(index).lowercaseString

            if modifiedDateString.containsString(threeLetterMonthString) {

                modifiedDateString = modifiedDateString.stringByReplacingOccurrencesOfString(threeLetterMonthString, withString: monthLocale)

                break
            }
        }

        return super.dateFromString(modifiedDateString)
    }

    return date
}

}
fisher
  • 1,286
  • 16
  • 29
  • All date formats are documented in http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns. "MMM" stands for the "abbreviated month", but that is not necessarily three letters (as in "Sept"). – Martin R May 05 '16 at 10:23
  • Yes, I know that the format MMM does not imply 3-letters. So what can I use to define that it should be 3 letters? – fisher May 05 '16 at 10:40
  • 3
    I cannot see such a format in the Unicode documentation, so I am afraid that you have to create your own parser. – Martin R May 05 '16 at 10:44
  • Thanks for the clarification! I'll go ahead and do my own formatting:) – fisher May 05 '16 at 18:19
  • 1
    @fisher You don't have to necessarily create a new formatter/parser, you can also set month names explicitly on `NSDateFormatter`, ignoring locale settings completely. – Sulthan May 05 '16 at 18:35

2 Answers2

5

The other answers are right. This is not a standard unicode format so changing locale won't help you. However, you can set month names explicitly!

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "ddMMMyy"
dateFormatter.shortMonthSymbols = ["jan", "feb", "mar", "apr", "maj", "jun", "jul", "aug", "sep", "okt", "nov", "dec"];

let date = dateFormatter.dateFromString("01JUN16")
print(date)
Sulthan
  • 128,090
  • 22
  • 218
  • 270
2

You're out of luck with NSDateFormatter. Try this and you'll see:

print("Short month symbols: \(dateFormatter.shortMonthSymbols)")

This prints ["jan.", "feb.", "mars", "apr.", "maj", "juni", "juli", "aug.", "sep.", "okt.", "nov.", "dec."]

I don't know what's common in Sweden, but as far as NSDateFormatter is concerned, "JUN" is not a valid short date name for Swedish formats. Using shortStandaloneMonthSymbols gives nearly the same result ("Juni" rather than "Jun", at least), so replacing MMM with LLL isn't going to help either (though in some languages it does).

Tom Harrington
  • 69,312
  • 10
  • 146
  • 170