ios swift nsdate nscalendar

ios - primer y último día del mes actual en swift



nsdate nscalendar (8)

2017 ...

Primero, obtenga el mes que necesita:

let cal = Calendar.current let d = Calendar.current.date(byAdding: .month, value: 0, to: Date())! // for "last month" just use -1, for "next month" just use 1, etc

Para obtener el día de la semana para el primer día del mes:

let c = cal.dateComponents([.year, .month], from: d) let FDOM = cal.date(from: c)! let dowFDOM = cal.component(.weekday, from: FDOM) print("the day-of-week on the 1st is ... /(dowFDOM)") // so, that''s 1=Sunday, 2=Monday, etc.

Para obtener la cantidad de días en el mes:

let r = cal.range(of: .day, in: .month, for: d)! let kDays = r.count print("the number of days is ... /(kDays)")

Estoy tratando de obtener el primer y último día del mes rápidamente.

Hasta ahora tengo lo siguiente:

let dateFormatter = NSDateFormatter() let date = NSDate() dateFormatter.dateFormat = "yyyy-MM-dd" let calendar = NSCalendar.currentCalendar() let components = calendar.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: date) let month = components.month let year = components.year let startOfMonth = ("/(year)-/(month)-01")

Pero no estoy seguro de cómo obtener la última cita. ¿Hay un método incorporado que me falta? Obviamente tiene que tener en cuenta los años bisiestos, etc.


Extensiones rápidas 3 y 4

En realidad, esto se vuelve mucho más fácil con Swift 3+:

  1. Puede hacerlo sin protección (podría hacerlo si quisiera, pero como DateComponents es un tipo no opcional ahora, ya no es necesario).
  2. Al usar startOfDayForDate iOS 8 (ahora startOfDay ), no necesita configurar manualmente la hora a las 12 p.m. a menos que esté haciendo algunos cálculos de calendario realmente locos en todas las zonas horarias.

¡Vale la pena mencionar que algunas de las otras respuestas afirman que puede Calendar.current.date(byAdding: .month, value: 0, to: Date())! esto usando Calendar.current.date(byAdding: .month, value: 0, to: Date())! , pero donde esto falla, es que en realidad no se pone a cero el día, o no explica las diferencias en las zonas horarias.

Aqui tienes:

extension Date { func startOfMonth() -> Date { return Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: Calendar.current.startOfDay(for: self)))! } func endOfMonth() -> Date { return Calendar.current.date(byAdding: DateComponents(month: 1, day: -1), to: self.startOfMonth())! } } print(Date().startOfMonth()) // "2018-02-01 08:00:00 +0000/n" print(Date().endOfMonth()) // "2018-02-28 08:00:00 +0000/n"


Con Swift 3 y iOS 10, la forma más fácil de hacer esto es Calendar dateInterval(of:for:) :

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

A continuación, puede usar interval.start e interval.end para obtener las fechas que necesita.


Con Swift 3, puede elegir uno de los dos patrones siguientes para recuperar el primer y último día de un mes.

# 1 Uso de Calendar dateComponents(_:from:) , date(from:) y date(byAdding:to:wrappingComponents:) métodos

Con este patrón, primero obtiene la fecha del primer día de un mes, luego agrega un mes y elimina un día para obtener la fecha del último día del mes. El siguiente código de Playground muestra cómo configurarlo:

import Foundation // Set calendar and date let calendar = Calendar.current let date = calendar.date(byAdding: DateComponents(day: -10), to: Date())! // Get first day of month let firstDayComponents = calendar.dateComponents([.year, .month], from: date) let firstDay = calendar.date(from: firstDayComponents)! // Get last day of month let lastDayComponents = DateComponents(month: 1, day: -1) let lastDay = calendar.date(byAdding: lastDayComponents, to: firstDay)! // Set date formatter let dateFormatter = DateFormatter() dateFormatter.locale = Locale(identifier: "en_UK") dateFormatter.dateStyle = .long dateFormatter.timeStyle = .long // Print results print(dateFormatter.string(from: date)) // Prints: 22 March 2017 at 18:07:15 CET print(dateFormatter.string(from: firstDay)) // Prints: 1 March 2017 at 00:00:00 CET print(dateFormatter.string(from: lastDay)) // Prints: 31 March 2017 at 00:00:00 CEST

# 2 Uso del range(of:in:for:) Calendar range(of:in:for:) , dateComponents(_:from:) y date(from:) y métodos

Con este patrón, obtiene un rango de valores de día absolutos en un mes y luego recupera las fechas del primer día y el último día del mes. El siguiente código de Playground muestra cómo configurarlo:

import Foundation // Set calendar and date let calendar = Calendar.current let date = calendar.date(byAdding: DateComponents(day: -10), to: Date())! // Get range of days in month let range = calendar.range(of: .day, in: .month, for: date)! // Range(1..<32) // Get first day of month var firstDayComponents = calendar.dateComponents([.year, .month], from: date) firstDayComponents.day = range.lowerBound let firstDay = calendar.date(from: firstDayComponents)! // Get last day of month var lastDayComponents = calendar.dateComponents([.year, .month], from: date) lastDayComponents.day = range.upperBound - 1 //lastDayComponents.day = range.count // also works let lastDay = calendar.date(from: lastDayComponents)! // Set date formatter let dateFormatter = DateFormatter() dateFormatter.locale = Locale(identifier: "en_UK") dateFormatter.dateStyle = .long dateFormatter.timeStyle = .long // Print results print(dateFormatter.string(from: date)) // prints: 22 March 2017 at 18:07:15 CET print(dateFormatter.string(from: firstDay)) // prints: 1 March 2017 at 00:00:00 CET print(dateFormatter.string(from: lastDay)) // prints: 31 March 2017 at 00:00:00 CEST


En Swift 3, si pone el componente 0 al día, puede obtener el último día del mes. Hay un código de ejemplo:

public func isMoreDays(date: Date, asc: Bool)->Bool{ //components var dayComponents = self.getDateComponents(date: date) //asc is true if ascendant or false if descendant dayComponents.day = asc ? 0 : 1 //plus 1 to month ''cos if you set up day to 0 you are going to the previous month dayComponents.month = asc ? dayComponents.month! + 1 : dayComponents.month //instantiate calendar and get the date let calendar : Calendar = NSCalendar.current let day = calendar.date(from: dayComponents) //date comparison if(day?.compare(date) == .orderedSame){ return false } return true }


Obtienes el primer día del mes simplemente con

let components = calendar.components([.Year, .Month], fromDate: date) let startOfMonth = calendar.dateFromComponents(components)! print(dateFormatter.stringFromDate(startOfMonth)) // 2015-11-01

Para obtener el último día del mes, agregue un mes y reste un día:

let comps2 = NSDateComponents() comps2.month = 1 comps2.day = -1 let endOfMonth = calendar.dateByAddingComponents(comps2, toDate: startOfMonth, options: [])! print(dateFormatter.stringFromDate(endOfMonth)) // 2015-11-30

Alternativamente, use el método rangeOfUnit que le proporciona el inicio y la duración del mes:

var startOfMonth : NSDate? var lengthOfMonth : NSTimeInterval = 0 calendar.rangeOfUnit(.Month, startDate: &startOfMonth, interval: &lengthOfMonth, forDate: date)

Para una fecha el último día del mes, agregue la duración del mes menos un segundo:

let endOfMonth = startOfMonth!.dateByAddingTimeInterval(lengthOfMonth - 1)


Swift 3

Ejemplo de muchas fechas para:

Últimos 6 meses , últimos 3 meses , ayer, últimos 7 días, últimos 30 días, mes anterior, inicio y final del mes actual , fecha de inicio y finalización del último mes

let startDate = dateFormatter.string(from: Date().getThisMonthStart()!) let endDate = dateFormatter.string(from: Date().getThisMonthEnd()!) extension Date { func getLast6Month() -> Date? { return Calendar.current.date(byAdding: .month, value: -6, to: self) } func getLast3Month() -> Date? { return Calendar.current.date(byAdding: .month, value: -3, to: self) } func getYesterday() -> Date? { return Calendar.current.date(byAdding: .day, value: -1, to: self) } func getLast7Day() -> Date? { return Calendar.current.date(byAdding: .day, value: -7, to: self) } func getLast30Day() -> Date? { return Calendar.current.date(byAdding: .day, value: -30, to: self) } func getPreviousMonth() -> Date? { return Calendar.current.date(byAdding: .month, value: -1, to: self) } // This Month Start func getThisMonthStart() -> Date? { let components = Calendar.current.dateComponents([.year, .month], from: self) return Calendar.current.date(from: components)! } func getThisMonthEnd() -> Date? { let components:NSDateComponents = Calendar.current.dateComponents([.year, .month], from: self) as NSDateComponents components.month += 1 components.day = 1 components.day -= 1 return Calendar.current.date(from: components as DateComponents)! } //Last Month Start func getLastMonthStart() -> Date? { let components:NSDateComponents = Calendar.current.dateComponents([.year, .month], from: self) as NSDateComponents components.month -= 1 return Calendar.current.date(from: components as DateComponents)! } //Last Month End func getLastMonthEnd() -> Date? { let components:NSDateComponents = Calendar.current.dateComponents([.year, .month], from: self) as NSDateComponents components.day = 1 components.day -= 1 return Calendar.current.date(from: components as DateComponents)! } }


Swift 4

Si solo necesita el día ordinal:

func lastDay(ofMonth m: Int, year y: Int) -> Int { let cal = Calendar.current var comps = DateComponents(calendar: cal, year: y, month: m) comps.setValue(m + 1, for: .month) comps.setValue(0, for: .day) let date = cal.date(from: comps)! return cal.component(.day, from: date) } lastDay(ofMonth: 2, year: 2018) // 28 lastDay(ofMonth: 2, year: 2020) // 29