Как получить текущую дату в Cocoa


я начинаю разработку для iPhone, и поэтому я смотрю на разные учебники в интернете, а также пробую некоторые разные вещи. В настоящее время я пытаюсь создать обратный отсчет до полуночи. Чтобы получить количество часов, минут и секунд, я делаю следующее (что я нашел где-то):

NSDate* now = [NSDate date];

int hour = 23 - [[now dateWithCalendarFormat:nil timeZone:nil] hourOfDay];
int min = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] minuteOfHour];
int sec = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] secondOfMinute];
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min,sec];

однако, каждое место я использую -dateWithCalendarFormat:timeZone: Я получаю следующую ошибку:

warning: 'NSDate' may not respond to '-dateWithCalendarFormat:timeZone:'
(Messages without a matching method signature will be assumed to return 'id' and accept '...' as arguments.)
warning: no '-hourOfDay' method found
error: invalid operands to binary - (have 'int' and 'id')

это кажется чем-то очень простым. Что я не хватает?

кроме того, я заметил в разных местах и в разное время звездочка (*) находится либо сразу после времени NSDate* now или прямо перед переменной NSDate *now. В чем разница между ними и почему вы используете один против другого?

14 58

14 ответов:

вы должны использовать следующее:

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [gregorian components:(NSHourCalendarUnit  | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:yourDateHere];
NSInteger hour = [dateComponents hour];
NSInteger minute = [dateComponents minute];
NSInteger second = [dateComponents second];
[gregorian release];

нет никакой разницы между NSDate* now и NSDate *now, это просто вопрос предпочтения. С точки зрения компилятора, ничего не меняется.

у вас есть проблемы с iOS 4.2? Используйте этот код:

NSDate *currDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:@"dd.MM.YY HH:mm:ss"];
NSString *dateString = [dateFormatter stringFromDate:currDate];
NSLog(@"%@",dateString);

-->20.01.2011 10:36:02

вы также можете использовать:


CFGregorianDate currentDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), CFTimeZoneCopySystem());
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02.0f", currentDate.hour, currentDate.minute, currentDate.second];
CFRelease(currentDate); // Don't forget this! VERY important

Я думаю, что это имеет следующие преимущества:

  1. нет прямого выделения памяти.
  2. секунды-это двойной вместо целого числа.
  3. нет сообщения.
  4. быстрее.

// вы можете получить текущую дату/время с помощью следующего кода:

    NSDate* date = [NSDate date];
    NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
    NSTimeZone *destinationTimeZone = [NSTimeZone systemTimeZone];
    formatter.timeZone = destinationTimeZone;
    [formatter setDateStyle:NSDateFormatterLongStyle];
    [formatter setDateFormat:@"MM/dd/yyyy hh:mma"];
    NSString* dateString = [formatter stringFromDate:date];

заменить:

NSDate* now = [NSDate date];
int hour = 23 - [[now dateWithCalendarFormat:nil timeZone:nil] hourOfDay];
int min = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] minuteOfHour];
int sec = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] secondOfMinute];
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min,sec];

С этого:

NSDate* now = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [gregorian components:(NSHourCalendarUnit  | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:now];
NSInteger hour = [dateComponents hour];
NSInteger minute = [dateComponents minute];
NSInteger second = [dateComponents second];
[gregorian release];
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, minute, second];

кроме того, я заметил в разных местах и в разное время звездочка (*) находится либо сразу после времени NSDate* now или прямо перед переменной NSDate *now. В чем разница между ними и почему вы используете один против другого?

компилятору все равно, но ставить звездочку перед пробелом может ввести в заблуждение. Вот мой пример:

int* a, b;

что то типа b?

если вы угадал int *, вы ошибаетесь. Это просто int.

другой способ делает это немного яснее, сохраняя * рядом с переменной, к которой он принадлежит:

int *a, b;

конечно, есть два способа, которые еще яснее, чем это:

int b, *a;

int *a;
int b;

вам нужно сделать что-то вроде следующего:

NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSHourCalendarUnit fromDate:now];
NSLog(@"%d", [components hour]);

и так далее.

вот еще один способ:

NSDate *now = [NSDate date];

//maybe not 100% approved, but it works in English.  You could localize if necessary
NSDate *midnight = [NSDate dateWithNaturalLanguageString:@"midnight tomorrow"]; 

//num of seconds between mid and now
NSTimeInterval timeInt = [midnight timeIntervalSinceDate:now];
int hours = (int) timeInt/3600;
int minutes = ((int) timeInt % 3600) / 60;
int seconds = (int) timeInt % 60;

вы теряете субсекундных точности с литой NSTimeInterval в int, но это не должно волновать.

NSDate* now и NSDate *now то же самое: указатель на объект NSDate.

вы, вероятно, хотите использовать descriptionWithCalendarFormat:часовой пояс: locale:, а не dateWithCalendarFormat: - последний возвращает NSCalendarDate, который, как говорят документы, должен быть устаревшим в какой-то момент.

оригинальный плакат-способ определения секунд до полуночи не будет работать в день, когда начинается или заканчивается переход на летнее время. Вот кусок кода, который показывает как это сделать... Это будет в количестве секунд (NSTimeInterval); вы можете сделать деление/модуль/etc, чтобы добраться до того, что вам нужно.

NSDateComponents *dc = [[NSCalendar currentCalendar] components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:[NSDate date]];
[dc setDay:dc.day + 1];
NSDate *midnightDate = [[NSCalendar currentCalendar] dateFromComponents:dc];
NSLog(@"Now: %@, Tonight Midnight: %@, Hours until midnight: %.1f", [NSDate date], midnightDate, [midnightDate timeIntervalSinceDate:[NSDate date]] / 60.0 / 60.0);

нет никакой разницы в расположении звездочки (at в C, на котором основан Obj-C, это не имеет значения). Это чисто предпочтение (стиль).

Мне потребовалось некоторое время, чтобы найти, почему образец приложения работает, но мой нет.

библиотека (фонд.Framework), на который ссылается автор, - это системная библиотека (из ОС), где iPhone sdk (я использую 3.0) больше не поддерживается.

поэтому пример приложения (от about.com, http://www.appsamuck.com/day1.html) работает, но наши не делают.

CFGregorianDate currentDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), CFTimeZoneCopySystem());
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%2.0f", currentDate.hour, currentDate.minute, currentDate.second];

Марк был прав этот код намного эффективнее для управления датами часов мин и сек. Но он забыл @ в начале объявления строки формата.

+ (NSString *)displayCurrentTimeWithAMPM 
{
    NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
    [outputFormatter setDateFormat:@"h:mm aa"];

    NSString *dateTime = [NSString stringWithFormat:@"%@",[outputFormatter stringFromDate:[NSDate date]]];

    return dateTime;
}

возвращение 3: 33 утра