【问题标题】:How to get start date and end date of the current month (Swift 3)如何获取当月的开始日期和结束日期(Swift 3)
【发布时间】:2016-12-19 05:49:56
【问题描述】:

我正在尝试以dd/MM/yyyy 格式获取当前月份的开始日期和结束日期。我尝试使用SO Question 中回答的扩展名。但这似乎不是我想要的(格式不同,而且它给了我上个月的最后一个日期和当前月份的最后一个日期)。谁能帮帮我。

扩展类:

extension Date {
    func startOfMonth() -> Date? {
        let comp: DateComponents = Calendar.current.dateComponents([.year, .month, .hour], from: Calendar.current.startOfDay(for: self))
        return Calendar.current.date(from: comp)!
    }

    func endOfMonth() -> Date? {
        var comp: DateComponents = Calendar.current.dateComponents([.month, .day, .hour], from: Calendar.current.startOfDay(for: self))
        comp.month = 1
        comp.day = -1
        return Calendar.current.date(byAdding: comp, to: self.startOfMonth()!)
    }
}

我的结构:

struct Constants{

    // keys required for making a Login call (POST Method)
    struct LoginKeys {
       .....
    }

    struct RankingKeys {

        static let DateFrom = String(describing: Date().startOfMonth()) //giving me 2016-11-30 16:00:00 +0000 
        static let DateTo  = String(describing: Date().endOfMonth())
//2016-12-30 16:00:00 +0000
    }
}

预期结果:

DateFrom  = "01/12/2016"
DateTo = "31/12/2016"

【问题讨论】:

  • 可能是时区问题。
  • 连日期都错了。开始日期应为 12 月的第一天,结束日期应为 31 日,但输出不同
  • 你的代码没问题。您在当地时间获得正确的值。请了解如何阅读记录 Date 对象的输出。注意输出中的时区。
  • @ASN 我有获取月末日期的功能,如果你愿意?我也会尝试获取每月的第一个日期
  • 澄清一下,您的计算是正确的。您只需要使用DateFormatterDate 正确转换为String

标签: ios date swift3 nsdate nsdateformatter


【解决方案1】:

你应该写这个简单的代码:

let dateFormatter = DateFormatter()
let date = Date()
dateFormatter.dateFormat = "dd-MM-yyyy"

开始日期:

let comp: DateComponents = Calendar.current.dateComponents([.year, .month], from: date)
let startOfMonth = Calendar.current.date(from: comp)!
print(dateFormatter.string(from: startOfMonth))

结束日期:

var comps2 = DateComponents()
comps2.month = 1
comps2.day = -1
let endOfMonth = Calendar.current.date(byAdding: comps2, to: startOfMonth)
print(dateFormatter.string(from: endOfMonth!)) 

【讨论】:

  • 此方法比实际开始日期少一天。例如,对于日期 2020-09-16,它应该给出 2020-09-01,但它给出的是 2020-08-31
  • 这可能是由 print iso 输出引起的,所以可能与您居住的地方有几个小时不同 - 所以这是故意的。(时区)尝试以格式化的方式输出,应该没问题。
【解决方案2】:

这就是我正在使用的。很简单,但很有效。

extension Calendar {

func dayOfWeek(_ date: Date) -> Int {
    var dayOfWeek = self.component(.weekday, from: date) + 1 - self.firstWeekday

    if dayOfWeek <= 0 {
        dayOfWeek += 7
    }

    return dayOfWeek
}

func startOfWeek(_ date: Date) -> Date {
    return self.date(byAdding: DateComponents(day: -self.dayOfWeek(date) + 1), to: date)!
}

func endOfWeek(_ date: Date) -> Date {
    return self.date(byAdding: DateComponents(day: 6), to: self.startOfWeek(date))!
}

func startOfMonth(_ date: Date) -> Date {
    return self.date(from: self.dateComponents([.year, .month], from: date))!
}

func endOfMonth(_ date: Date) -> Date {
    return self.date(byAdding: DateComponents(month: 1, day: -1), to: self.startOfMonth(date))!
}

func startOfQuarter(_ date: Date) -> Date {
    let quarter = (self.component(.month, from: date) - 1) / 3 + 1
    return self.date(from: DateComponents(year: self.component(.year, from: date), month: (quarter - 1) * 3 + 1))!
}

func endOfQuarter(_ date: Date) -> Date {
    return self.date(byAdding: DateComponents(month: 3, day: -1), to: self.startOfQuarter(date))!
}

func startOfYear(_ date: Date) -> Date {
    return self.date(from: self.dateComponents([.year], from: date))!
}

func endOfYear(_ date: Date) -> Date {
    return self.date(from: DateComponents(year: self.component(.year, from: date), month: 12, day: 31))!
}
}

如何使用

let calendar: Calendar = Calendar.current
let startDate = calendar.startOfMonth(Date())
print("startDate :: \(startDate)")

【讨论】:

  • @Hung Hoang 如果您提供示例如何在一行中使用,那将是非常高兴的。这对用户来说会更有价值。
【解决方案3】:

这是一个为 Date 创建扩展的简单解决方案,如下所示:

extension Date {

func startOfMonth() -> Date {
    let interval = Calendar.current.dateInterval(of: .month, for: self)
    return (interval?.start.toLocalTime())! // Without toLocalTime it give last months last date
}

func endOfMonth() -> Date {
    let interval = Calendar.current.dateInterval(of: .month, for: self)
    return interval!.end
}

// Convert UTC (or GMT) to local time
func toLocalTime() -> Date {
    let timezone    = TimeZone.current
    let seconds     = TimeInterval(timezone.secondsFromGMT(for: self))
    return Date(timeInterval: seconds, since: self)
}}

然后像这样调用你的 Date 实例

print(Date().startOfMonth())
print(Date().endOfMonth())

【讨论】:

  • 太好了,谢谢!这解决了我的问题。
  • 这个解决方案可以挽救生命!真的清理了我的代码!
【解决方案4】:

使用 Swift 3 和 iOS 10,我发现最简单的方法是 Calendar's dateInterval(of:for:)

guard let interval = calendar.dateInterval(of: .month, for: Date()) else { return }

然后使用日期格式化程序打印日期:

let formatter = DateFormatter()
formatter.dateFormat = "dd-MM-yyyy"
let dateText = formatter.string(from: interval.start)

【讨论】:

    【解决方案5】:

    此扩展可根据您的需要为您提供预期的输出

    这里我返回日期

    extension NSDate {
        func startOfMonth() -> NSDate? {
            guard
                let cal: NSCalendar = NSCalendar.currentCalendar(),
                let comp: NSDateComponents = cal.components([.Year, .Month], fromDate: self) else { return nil }
            comp.to12pm()
            let dateformattor = NSDateFormatter()
            dateformattor.dateFormat = "yyyy-MM-dd"
            dateformattor.timeZone = NSTimeZone.localTimeZone()
            let dt2 = dateformattor.stringFromDate(cal.dateFromComponents(comp)!)
            print(dt2)
    
            dateformattor.dateFormat = "yyyy-MM-dd"
            dateformattor.timeZone = NSTimeZone.init(abbreviation: "UTC")
    
            return dateformattor.dateFromString(dt2)
        }
    
        func endOfMonth() -> NSDate? {
            guard
                let cal: NSCalendar = NSCalendar.currentCalendar(),
                let comp: NSDateComponents = NSDateComponents() else { return nil }
            comp.month = 1
            comp.day = -1
            comp.to12pm()
            let dateformattor = NSDateFormatter()
            dateformattor.dateFormat = "yyyy-MM-dd"
            dateformattor.timeZone = NSTimeZone.localTimeZone()
            let dt2 = dateformattor.stringFromDate(cal.dateByAddingComponents(comp, toDate: self.startOfMonth()!, options: [])!)
    
            dateformattor.dateFormat = "yyyy-MM-dd"
            dateformattor.timeZone = NSTimeZone.init(abbreviation: "UTC")
    
            return dateformattor.dateFromString(dt2)
        }
    }
    internal extension NSDateComponents {
        func to12pm() {
            self.hour = 12
            self.minute = 0
            self.second = 0
        }
    }
    

    **输出:- **

    Start Date of Month :- 2016-12-01 00:00:00 +0000
    End Date of Month :- 2016-12-31 00:00:00 +0000
    

    【讨论】:

    • 问题是如何在 Swift 3 中做到这一点。这是 Swift 2 的答案。
    • @Rob 我要求提问者在 swift 2.2 中发布答案,在他允许后我发布它
    • 这段代码有很多问题。为什么在创建日期之前将组件设置为下午 12 点?日期格式化程序默认为本地时间,因此无需明确将其设置为本地时间。为什么要将日期转换为字符串,然后再转换回 UTC 日期?大部分贴出的代码都是不必要的。
    【解决方案6】:

    为了完整起见,Calendar 的 API dateInterval(of:start:interval:for:) 将当前month 的开始日期和间隔(以秒为单位)分配给inout 参数。

    日期格式化程序考虑当前时区。

    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.dateFormat = "dd/MM/yyyy"
    
    var startDate = Date()
    var interval = TimeInterval()
    Calendar.current.dateInterval(of: .month, start: &startDate, interval: &interval, for: Date())
    let endDate = Calendar.current.date(byAdding: .second, value: Int(interval) - 1, to: startDate)!
    
    let fromDate = formatter.string(from: startDate)
    let toDate = formatter.string(from: endDate)
    print(fromDate, toDate)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      相关资源
      最近更新 更多