NSDate obtener año / mes / día

291

¿Cómo puedo obtener el año / mes / día de un NSDateobjeto, sin otra información? Me doy cuenta de que probablemente podría hacer esto con algo similar a esto:

NSCalendar *cal = [[NSCalendar alloc] init];
NSDateComponents *components = [cal components:0 fromDate:date];
int year = [components year];
int month = [components month];
int day = [components day];

Pero eso parece ser una molestia para algo tan simple como obtener un NSDateaño / mes / día. hay alguna otra solucion?

Richard J. Ross III
fuente
44
Tuve algunos problemas para usar este código hasta que cambié la primera línea a "NSCalendar * cal = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];" Debe haber habido un cambio en la API desde que se hizo esta pregunta.
Russell Thackston el
@ futureelite7 regresó a la revisión 1. El código que existe es para fines históricos y fue una explicación simple de cuál era mi idea inicial.
Richard J. Ross III
El código ya no funciona. ¿Puedes anotar el código correcto?
futureelite7
@ futureelite7 no. Ese código fue una muestra de mi primer intento, nunca tuvo la intención de funcionar. Si cree que eso es ambiguo, no dude en editar el contexto que rodea ese bloque de código, pero no edite el código en sí. Si te gusta mucho editar el código en sí, entonces lleva esta cobertura a meta y veremos qué tienen que decir otros mods.
Richard J. Ross III
8
@ Mike es por eso que lees las respuestas, no la pregunta.
Richard J. Ross III

Respuestas:

615

Como aparentemente esta es mi respuesta más popular, intentaré editarla para que contenga un poco más de información.

A pesar de su nombre, NSDateen sí mismo simplemente marca un punto en el tiempo de la máquina, no una fecha. No existe una correlación entre el punto en el tiempo especificado por un NSDateaño, mes o día. Para eso, debes consultar un calendario. Cualquier momento dado devolverá información de fecha diferente según el calendario que esté mirando (las fechas no son las mismas en los calendarios gregoriano y judío, por ejemplo), y aunque el calendario gregoriano es el calendario más utilizado en el mundo, supongo, estamos un poco sesgados que NSDatesiempre deberían usarlo. NSDateAfortunadamente, es mucho más bipartidista.


Obtendrá la fecha y la hora NSCalendar, como mencionó, pero hay una manera más simple de hacerlo:

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];

Eso genera un NSDateComponentsobjeto que contiene el día, mes y año del calendario actual del sistema para el día actual. ( Nota: este no es necesariamente el calendario actual especificado por el usuario , solo el sistema predeterminado).

Por supuesto, si está usando un calendario o fecha diferente, puede cambiarlo fácilmente. Se puede encontrar una lista de calendarios y unidades de calendario disponibles en la NSCalendarReferencia de clase . Se NSDateComponentspuede encontrar más información sobre la NSDateComponentsReferencia de clase .


Como referencia, acceder a componentes individuales desde NSDateComponentses bastante fácil:

NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];

Solo debe tener en cuenta: NSDateComponentsno contendrá información válida para los campos que solicite a menos que los haya generado con esa información válida (es decir, solicite NSCalendarproporcionar esa información con NSCalendarUnits). NSDateComponentsno contienen información de referencia en sí mismas: son solo estructuras simples que contienen números para que usted acceda. Si desea obtener una era, por ejemplo, fuera de NSDateComponents, tendrá que alimentar el método generador NSCalendarcon la NSCalendarUnitErabandera.

Itai Ferber
fuente
3
Una corrección a esto, la primera línea debe tener NSDayCalendarUnit en lugar de NSWeekCalendarUnit.
whitehawk
@Erik ¿Qué calendario estás usando? ¿Código?
Itai Ferber
77
@ Jonny Los resultados que obtienes dependen del calendario que estés usando. NSCalendarEl +currentCalendarmétodo devolverá el calendario del sistema, por lo que si el teléfono del usuario está configurado en el modo de hora japonés o tailandés, obtendrá un año diferente. Si desea forzar un sistema de calendario específico, cree un calendario e inicialícelo con la configuración regional adecuada. Por ejemplo, para forzar un calendario gregoriano, querrás usar lo siguiente:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
Itai Ferber
2
enumeraciones NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit son DEPRECATED use NSCalendarUnitDay en su lugar.
Kunal Balani
2
Advertencia: no utilice [NSCalendar currentCalendar] a menos que esté intentando mostrar un valor al usuario. Tenga en cuenta que los usuarios pueden seguir un calendario budista (el año ahora es 2558 o algo así), o cualquier otro número de calendarios impares. No desea que su aplicación se rompa en estos casos. Use el calendario gregoriano a menos que tenga una razón muy específica para no hacerlo. Este error es difícil de detectar porque usted y sus evaluadores pueden usar gregorian por defecto.
n13
51

Puede obtener un componente separado de un NSDate usando NSDateFormatter:

NSDateFormatter *df = [[NSDateFormatter alloc] init];

[df setDateFormat:@"dd"];
myDayString = [df stringFromDate:[NSDate date]];

[df setDateFormat:@"MMM"];
myMonthString = [df stringFromDate:[NSDate date]];

[df setDateFormat:@"yy"];
myYearString = [df stringFromDate:[NSDate date]];

Si desea obtener el número del mes en lugar de la abreviatura, use "MM". Si desea obtener enteros, use[myDayString intValue];

skocko76
fuente
1
Ampliado sobre el suyo con esta esencia . Diviértete --- puedes colocar esto en tu código.
DogEatDog
Resolvió mi problema por usar fechas para buscar en un diccionario :) ¡Gracias!
mlunoe
1
En realidad, esto no funciona al 100% como se esperaba todo el tiempo. Por ejemplo, si el NSDate es 2013-12-31 00:00:00 +0000, la fecha formateada devolverá 2014 para el año, incluso si el número real en la fecha es 2013.
margusholland
¿Cómo puedo obtener el día del año, por ejemplo, el 10 de abril es el día actual es el día 99 del año actual? -
Desarrollador iOS
17

Solo para reformular el excelente código de Itai (¡y funciona!), Así es como se vería una clase auxiliar de muestra, para devolver el valor del año de una variable NSDate dada.

Como puede ver, es bastante fácil modificar este código para obtener el mes o el día.

+(int)getYear:(NSDate*)date
{
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:date];

    int year = [components year];
    int month = [components month];
    int day = [components day];

    return year;
}

(No puedo creer que tengamos que escribir nuestras propias funciones básicas de fecha de iOS como esta, en 2013 ...)

Otra cosa: nunca use <y> para comparar dos valores NSDate.

XCode aceptará felizmente dicho código (sin errores ni advertencias), pero sus resultados son una lotería. Usted debe utilizar la función "Comparar" compara NSDates:

if ([date1 compare:date2] == NSOrderedDescending) {
    // date1 is greater than date2        
}
Mike Gledhill
fuente
44
Los resultados de la comparación de punteros están lejos de ser una lotería: tienen resultados muy bien definidos, siempre que los use para lo que están destinados: comparar punteros, no objetos.
Richard J. Ross III
Puede que no sea una lotería, pero DateTime de C # es mucho más intuitivo. En iOS, el operador menor que realmente debería comparar dos NSDates ... ¿alguien realmente querría comparar los punteros de dos variables NSDate? Por lo menos, XCode show muestra una Advertencia para preguntar si esto es realmente lo que el usuario realmente quiere decir.
Mike Gledhill
1
Eso es solo una señal de un codificador perezoso que no comprende los fundamentos del lenguaje en el que está escribiendo. Y, para mí, ha habido situaciones en las que las comparaciones de punteros son necesarias para los objetos ObjC, especialmente si está haciendo un contenedor personalizado (aunque las cosas se vuelven más raras con ARC).
Richard J. Ross III
1
Debo ser un codificador perezoso que no entiende los fundamentos, ¡pero ese es un gran consejo Mike!
Pier-Luc Gendreau
44
Las comparaciones de punteros pueden ser necesarias, pero son el caso de uso mucho menos común al comparar dos fechas. El 99,99% de las veces cualquier programador estaría más interesado en comparar las fechas en lugar de los punteros. Fundamentalmente, C # y .NET Framework fueron diseñados para facilitar los escenarios más comunes, lo que hace que los programadores sean más productivos y, en muchos casos, el objetivo-c parece que hace las cosas intencionalmente más arduas. Si tienes tiempo para leer un libro de 800 páginas sobre los fundamentos de cada idioma, aclama, pero el resto de nosotros tenemos aplicaciones para entregar a tiempo y dentro del presupuesto.
Crake
16

En Swift 2.0:

    let date = NSDate()
    let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
    let components = calendar.components([.Month, .Day], fromDate: date)

    let (month, day) = (components.month, components.day)
NatashaTheRobot
fuente
11

Estoy escribiendo esta respuesta porque es el único enfoque que no te devuelve opciones de las NSDateComponentvariables y / o fuerza el desenvolvimiento de esas variables (también para Swift 3).

Swift 3

let date = Date()
let cal = Calendar.current
let year = cal.component(.year, from: date)
let month = cal.component(.month, from: date)
let day = cal.component(.day, from: date)

Swift 2

let date = NSDate()
let cal = NSCalendar.currentCalendar()
let year = cal.component(.Year, fromDate: date)
let month = cal.component(.Month, fromDate: date)
let day = cal.component(.Day, fromDate: date)

Bonus Swift 3 versión divertida

let date = Date()
let component = { (unit) in return Calendar.current().component(unit, from: date) }
let year = component(.year)
let month = component(.month)
let day = component(.day)
Kevin
fuente
¿Cómo puedo obtener el día del año, por ejemplo, el 10 de abril es el día actual es el día 99 del año actual? -
Desarrollador iOS
Y asegúrese de usar el calendario gregoriano, por ejemplo, el componente de año para el calendario japonés devuelve 1 dígito.
Flovettee
8

Nuevo en iOS 8

ObjC

NSDate *date = [NSDate date];
NSInteger era, year, month, day;
[[NSCalendar currentCalendar] getEra:&era year:&year month:&month day:&day fromDate:date];

Rápido

let date = NSDate.init()
var era = 0, year = 0, month = 0, day = 0
NSCalendar.currentCalendar().getEra(&era, year:&year, month:&month, day:&day, fromDate: date)
Yuchen Zhong
fuente
2
¡Asombroso! @Yuchen Zhong
Lito
1
Brillante! Mucho mejor sintaxis!
joan
4

Si está apuntando a iOS 8+, puede usar los nuevos NSCalendarmétodos de conveniencia para lograr esto en un formato más conciso.

Primero cree un NSCalendary use lo que NSDatesea ​​necesario.

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *date = [NSDate date];

Puede extraer componentes individualmente a través de component:fromDate:

NSInteger year = [calendar component:NSCalendarUnitYear fromDate:date];
NSInteger month = [calendar component:NSCalendarUnitMonth fromDate:date];
NSInteger day = [calendar component:NSCalendarUnitDay fromDate:date];

O, aún más sucintamente, use NSIntegerpunteros a través degetEra:year:month:day:fromDate:

NSInteger year, month, day;
[calendar getEra:nil year:&year month:&month day:&day fromDate:date];

Para obtener más información y ejemplos, consulte NSDate Manipulation Made Easy en iOS 8 . Descargo de responsabilidad, escribí la publicación.

Joe Masilotti
fuente
¿Cómo puedo obtener el día del año, por ejemplo, el 10 de abril es el día actual es el día 99 del año actual? -
Desarrollador iOS
4

A partir de iOS 8.0 (y OS X 10), puede usar el método del componente para simplificar la obtención de un único componente de fecha de la siguiente manera:

int year = [[NSCalendar currentCalendar] component:NSCalendarUnitYear fromDate:[NSDate date]];

Debería simplificar las cosas y, con suerte, esto se implementa de manera eficiente.

Christopher King
fuente
2
    NSDate *currDate = [NSDate date];
    NSCalendar*       calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents* components = [calendar components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:currDate];
    NSInteger         day = [components day];
    NSInteger         month = [components month];
    NSInteger         year = [components year];
    NSLog(@"%d/%d/%d", day, month, year);
Linh Nguyen
fuente
Eso claramente no me da el año, mes o día como un número entero, que es lo que solicité en el OP. -1.
Richard J. Ross III
1
Richard J. Ross III: Lo acabo de arreglar, lo siento porque mi respuesta perdió su pregunta.
Linh Nguyen
2

Aquí está la solución en Swift:

let todayDate = NSDate()
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!

// Use a mask to extract the required components. Extract only the required components, since it'll be expensive to compute all available values.
let components = calendar.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: todayDate)

var (year, month, date) = (components.year, components.month, components.day) 
Nitin Nain
fuente
2

Prueba esto . . .

Fragmento de código:

 NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
 int year = [components year];
 int month = [components month];
 int day = [components day];

Da año actual, mes, fecha

Yogeesh HT
fuente
1

Intenta lo siguiente:

    NSString *birthday = @"06/15/1977";
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"MM/dd/yyyy"];
    NSDate *date = [formatter dateFromString:birthday];
    if(date!=nil) {
        NSInteger age = [date timeIntervalSinceNow]/31556926;
        NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
        NSInteger day = [components day];
        NSInteger month = [components month];
        NSInteger year = [components year];

        NSLog(@"Day:%d Month:%d Year:%d Age:%d",day,month,year,age);
    }
    [formatter release];
loretoparisi
fuente
1

Swift 2.x

extension NSDate {
    func currentDateInDayMonthYear() -> String {
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "d LLLL yyyy"
        return dateFormatter.stringFromDate(self)
    }
}

Puedes usarlo como

NSDate().currentDateInDayMonthYear()

Salida

6 March 2016
Alserda
fuente
1

Rápido

La forma más fácil de obtener cualquier elemento de fecha como una cadena opcional.

extension Date {

  // Year 
  var currentYear: String? {
    return getDateComponent(dateFormat: "yy")
    //return getDateComponent(dateFormat: "yyyy")
  }

  // Month 
  var currentMonth: String? {
    return getDateComponent(dateFormat: "M")
    //return getDateComponent(dateFormat: "MM")
    //return getDateComponent(dateFormat: "MMM")
    //return getDateComponent(dateFormat: "MMMM")
  }


  // Day
  var currentDay: String? {
    return getDateComponent(dateFormat: "dd")
    //return getDateComponent(dateFormat: "d")
  }


  func getDateComponent(dateFormat: String) -> String? {
    let format = DateFormatter()
    format.dateFormat = dateFormat
    return format.string(from: self)
  }


}

let today = Date()
print("Current Year - \(today.currentYear)")  // result Current Year - Optional("2017")
print("Current Month - \(today.currentMonth)")  // result Current Month - Optional("7")
print("Current Day - \(today.currentDay)")  // result Current Day - Optional("10")
Krunal
fuente
0

lo hago de esta manera ...

NSDate * mydate = [NSDate date];

NSCalendar * mycalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSCalendarUnit units = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;

NSDateComponents * myComponents  = [mycalendar components:units fromDate:mydate];

NSLog(@"%d-%d-%d",myComponents.day,myComponents.month,myComponents.year);
Shaik Riyaz
fuente
0

Para obtener una cadena legible por humanos (día, mes, año), puede hacer lo siguiente:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *string = [dateFormatter stringFromDate:dateEndDate];
mirap
fuente