简体   繁体   English

NSDateFormatter:使用具有相对格式的自定义格式

[英]NSDateFormatter: Using custom format with relative formatting

I am trying to format NSDate s in a form where it uses the relative format when applicable and the day of the week when not: "Today", "Tomorrow", "Sunday", "Monday", …我试图以一种形式格式化NSDate s,它在适用时使用相对格式,不使用时使用星期几:“今天”、“明天”、“星期日”、“星期一”……

The problem is, NSDateFormatter 's doesRelativeFormatting only works when using dateStyle , and not with dateFormat .问题是, NSDateFormatterdoesRelativeFormatting仅在使用dateStyle时才有效,而在dateFormat时无效。 (Basically, I'd need the functionality of dateFormat = "EEEE" for all days after tomorrow.) (基本上,我需要在明天之后的所有日子里使用dateFormat = "EEEE"的功能。)

At the moment, I'm using the following code:目前,我正在使用以下代码:

let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = .NoStyle
dateFormatter.dateStyle = .FullStyle
dateFormatter.doesRelativeDateFormatting = true

let dateString = dateFormatter.stringFromDate(theDate)
return dateString.componentsSeparatedByString(" ")[0]

Which just happens to work in my specific locale where NSDateFormatterStyle.FullStyle outputs something like "Sunday 23 August 2015", but obviously that's not a good or general solution.这恰好适用于我的特定语言环境,其中NSDateFormatterStyle.FullStyle输出类似“2015 年 8 月 23 日星期日”的内容,但显然这不是一个好的或通用的解决方案。

The closest thing I found would be this question , but it seems unnecessarily complex for my use case, and I'd like something more elegant, if possible.我发现的最接近的事情是这个 question ,但对于我的用例来说似乎不必要地复杂,如果可能的话,我想要更优雅的东西。

Thanks!谢谢!

I'd use 3 date formatters:我会使用 3 个日期格式化程序:

  1. dateStyle = .FullStyle and doesRelativeDateFormatting = true dateStyle = .FullStyledoesRelativeDateFormatting = true
  2. dateStyle = .FullStyle and doesRelativeDateFormatting = false dateStyle = .FullStyledoesRelativeDateFormatting = false
  3. dateFormat = "EEEE" and doesRelativeDateFormatting = false dateFormat = "EEEE"doesRelativeDateFormatting = false

Get formatted strings for 1 and 2. If they are different, then use string from 1. If they are the same then get and use string from 3.获取 1 和 2 的格式化字符串。如果它们不同,则使用来自 1 的字符串。如果它们相同,则获取并使用来自 3 的字符串。

This should work reliably for all locales.这应该适用于所有语言环境。 For performance reasons make sure to keep all 3 formatters around instead of recreating them each time.出于性能原因,请确保保留所有 3 个格式化程序,而不是每次都重新创建它们。

Here's a working extension to DateFormatter() :这是DateFormatter()的工作扩展:

import Foundation

extension DateFormatter {

    /*
     * Returns a string representation of a given date in relative format.
     * If the current local doesn't offer a relative format for the given date,
     * then then a given format is applied.
     *
     * - parameter _date: The date to be formatted
     * - parameter _format: The format to be applied to non-relative dates
     *
     * - returns: A string representing a formatted version of a given date
     */

    func relativeStringWithFormat(from: Date, format: String) -> String? {

        // Create date formatters
        let _formatRelative = DateFormatter()
            _formatRelative.dateStyle = .full
            _formatRelative.doesRelativeDateFormatting = true
            _formatRelative.timeStyle = .none

        let _formatFull = DateFormatter()
            _formatFull.dateStyle = .full
            _formatFull.doesRelativeDateFormatting = false
            _formatFull.timeStyle = .none

        let _formatCustom = DateFormatter()
            _formatCustom.dateFormat = format
            _formatCustom.doesRelativeDateFormatting = false

        // Get dates in available formats
        let _dateRelative = _formatRelative.string(from: from)
        let _dateFull = _formatFull.string(from: from)
        let _dateCustom = _formatCustom.string(from: from)

        // Return appropriatly formatted date/string
        if _dateRelative != _dateFull {

            return _dateRelative

        } else {

            return _dateCustom
        }
    }   
}

@eranschau's answer doesn't cover localized dates, so I've added an optional parameter to set up Locale and also fixed a bug when the comparison won't work because unexpected uppercase in some cases. @eranschau 的回答不包括本地化日期,因此我添加了一个可选参数来设置 Locale,并且还修复了在某些情况下由于意外大写而无法进行比较时的错误。

extension DateFormatter
{
    /**
     * Returns a string representation of a given date in relative format.
     * If the current local doesn't offer a relative format for the given date,
     * then then a given format is applied.
     *
     * - parameter date: The date to be formatted
     * - parameter format: The format to be applied to non-relative dates
     * - parameter locale: The locale to be used for date formatting
     *
     * - returns: A string representing a formatted version of a given date
     */

    func relativeStringWithFormat(from: Date, format: String, locale: Locale? = nil) -> String
    {
        // Create date formatters
        let _formatRelative = DateFormatter()
            _formatRelative.dateStyle = .full
            _formatRelative.doesRelativeDateFormatting = true
            _formatRelative.timeStyle = .none
            _formatRelative.locale = locale ?? Locale.current

        let _formatFull = DateFormatter()
            _formatFull.dateStyle = .full
            _formatFull.doesRelativeDateFormatting = false
            _formatFull.timeStyle = .none
            _formatFull.locale = locale ?? Locale.current

        let _formatCustom = DateFormatter()
            _formatCustom.dateFormat = DateFormatter.dateFormat(fromTemplate: format, options: 0, locale: locale ?? Locale.current)

        // Get dates in available formats
        let _dateRelative = _formatRelative.string(from: from)
        let _dateFull = _formatFull.string(from: from)
        let _dateCustom = _formatCustom.string(from: from)

        // Return appropriatly formatted date/string
        if _dateRelative.caseInsensitiveCompare(_dateFull) != .orderedSame {
            return _dateRelative
        } else {
            return _dateCustom
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM