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+:
-
Puede hacerlo sin protección (podría hacerlo si quisiera, pero como
DateComponents
es un tipo no opcional ahora, ya no es necesario). -
Al usar
startOfDayForDate
iOS 8 (ahorastartOfDay
), 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