NSDate получить год / месяц / день - PullRequest
285 голосов
/ 12 сентября 2010

Как я могу получить год / месяц / день для объекта NSDate, если нет другой информации? Я понимаю, что мог бы сделать это с помощью чего-то подобного:

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

Но это, кажется, много хлопот для чего-то такого простого, как получение NSDate года / месяца / дня. Есть ли другое решение?

Ответы [ 17 ]

607 голосов
/ 12 сентября 2010

Поскольку это, по-видимому, мой самый популярный ответ, я постараюсь отредактировать его, чтобы он содержал немного больше информации.

Несмотря на свое название, NSDate само по себе просто обозначает точку в машиневремя, а не свиданиеНет корреляции между моментом времени, указанным NSDate, и годом, месяцем или днемДля этого вам нужно обратиться к календарю.Любой данный момент времени будет возвращать различную информацию о дате в зависимости от того, какой календарь вы просматриваете (например, даты не совпадают в григорианском и еврейском календарях), а григорианский календарь является наиболее широко используемым календарем вМир - я предполагаю - мы немного предвзяты, что NSDate всегда должен его использоватьNSDate, к счастью, гораздо более двухпартийен.


Получение даты и времени должно пройти через NSCalendar, как вы упоминали, но есть более простой способ сделать это:

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

Создает объект NSDateComponents, содержащий день, месяц и год из текущего системного календаря на текущий день.( Примечание: это не обязательно текущий указанный пользователем календарь, просто системный календарь по умолчанию.)

Конечно, если вы используете другойкалендарь или дата, вы можете легко изменить это.Список доступных календарей и календарных единиц можно найти в NSCalendar Ссылка на класс .Более подробную информацию о NSDateComponents можно найти в NSDateComponents Справочнике классов .


Для справки, доступ к отдельным компонентам из NSDateComponents довольно прост:

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

Вам просто нужно помнить: NSDateComponents не будет содержать действительную информацию для любых полей, которые вы запрашиваете, если вы не сгенерировали их с этой действительной информацией (т.е. запрос NSCalendar, чтобы предоставить эту информацию с NSCalendarUnitс).NSDateComponents сами по себе не содержат справочной информации - это просто простые структуры, которые содержат номера для доступа к ним.Если вы также хотите получить эпоху, например, из NSDateComponents, вам нужно передать метод генератора из NSCalendar с флагом NSCalendarUnitEra.

50 голосов
/ 15 декабря 2011

Вы можете получить отдельный компонент NSDate, используя 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]];

Если вы хотите получить номер месяца вместо сокращения, используйте «ММ». Если вы хотите получить целые числа, используйте [myDayString intValue];

17 голосов
/ 16 мая 2013

Просто чтобы перефразировать превосходный (и работающий!) Код Itai, вот как будет выглядеть пример вспомогательного класса для возврата значения year данной переменной NSDate.

Как видите, этот код достаточно легко изменить, чтобы получить месяц или день.

+(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;
}

(Я не могу поверить, что нам нужно написать наши собственные базовые функции даты iOS, как это, в 2013 году ...)

Еще одна вещь: никогда не используйте <и> для сравнения двух значений NSDate.

XCode с радостью примет такой код (без каких-либо ошибок или предупреждений), но его результаты - лотерея. Вы должны использовать функцию сравнения для сравнения NSDates:

if ([date1 compare:date2] == NSOrderedDescending) {
    // date1 is greater than date2        
}
14 голосов
/ 23 августа 2015

В 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)
11 голосов
/ 08 июля 2016

Я пишу этот ответ, потому что это единственный подход, который не возвращает вам необязательные аргументы из NSDateComponent переменных и / или не заставляет их развернуть (также для 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)

Бонус Swift 3 веселая версия

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)
8 голосов
/ 26 февраля 2016

Новое в iOS 8

ObjC

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

Swift

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)
4 голосов
/ 10 февраля 2015

Если вы нацелены на iOS 8+, вы можете использовать новые удобные методы NSCalendar, чтобы добиться этого в более кратком формате.

Сначала создайте NSCalendar и используйте все, что требуется NSDate.

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

Вы можете извлекать компоненты по отдельности с помощью component:fromDate:

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

или, еще более кратко, использовать NSInteger указатели с помощью getEra:year:month:day:fromDate:

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

Для получения дополнительной информации и примеров посмотрите NSDate Manipulation Made Easy в iOS 8 .Отказ от ответственности, я написал пост.

4 голосов
/ 16 сентября 2015

Начиная с iOS 8.0 (и OS X 10) вы можете использовать метод component , чтобы упростить получение одного компонента даты, например:

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

Должно сделать вещи проще и, надеюсь, это будет эффективно реализовано.

2 голосов
/ 07 апреля 2014
    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);
2 голосов
/ 22 июня 2015

Вот решение в 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) 
...