根据语言环境正确排序月份和日期

Properly ordering month and date according to locale

我想以人类可读的格式显示一周的开始和结束日期。使用 MMMM d 作为日期格式基础。例如:

- March 7 - 13
- February 28 - March 6
- 7-13 de marzo

因此,如果周开始和结束属于同一个月,我只想提及月份一次。我希望这在不同的语言环境中是准确的。例如,在西班牙语和白俄罗斯语中,日会在月之前,而在西班牙语中,会在月份名称前添加“de”。

我正在使用

DateFormatter.dateFormat(
                fromTemplate: "MMMM d",
                options: 0,
                locale: Locale(identifier: Bundle.main.preferredLocalizations.first

获取正确的格式,然后尝试解析它并用两个数字替换天数,以表示当周完全属于同一个月时。我意识到我的代码有点老套,可能无法保证适用于所有可能的语言环境。但我不知道有没有更简单/更好的方法。

这是我目前的情况:

func weekDateTitle(firstDay: Date, lastDay: Date) -> String {
    let dateTemplate = DateFormatter.dateFormat(
        fromTemplate: "MMMM d",
        options: 0,
        locale: Locale(identifier: Bundle.main.preferredLocalizations.first ?? "en"))
    let formatter = DateFormatter()

    // If the week ends on the same month as it begins, we use short label format,
    // like "Month X - Y"
    if firstDay.isSameMonth(as: lastDay) {
        formatter.dateFormat = "MMMM"
        let month = formatter.string(from: firstDay)
        
        formatter.dateFormat = "d"
        let days = "\(formatter.string(from: firstDay)) - \(formatter.string(from: lastDay))"
        
        return dateTemplate?
             .replacingFirstOccurrence(of: "MMMM", with: month)
             .replacingFirstOccurrence(of: "d", with: days)
             .replacingOccurrences(of: "'", with: "") ?? ""
    } else {
    // Not really important 
    }
}

考虑 DateIntervalFormatter:

let formatter = DateIntervalFormatter()

formatter.locale = locale
formatter.dateTemplate = "MMMMd"

let string = formatter.string(from: date1, to: date2)

对于同一个月,这将生成“7 – 13 de marzo”和“March 7 – 13”。

对于不同的月份,“7 de febrero – 13 de marzo”和“February 7 – Marzo 13”。

这些格式化程序存在奇怪的边缘情况(例如,.longdateStyle 在英语语言环境中有效,但在其他语言环境中无效)。如果以上内容在您的所有目标语言环境中无法完美运行,我也不会感到惊讶,因此您可能需要仔细检查。但是,根据我的经验,这些格式化程序可以让您非常接近。它似乎可以满足您对英语和西班牙语的需求……