как определить, есть ли nsdate сегодня?

<p>как проверить, принадлежит ли <code>nsdate</code> сегодня?</p><p>я проверял это, используя первые 10 символов из <code>[adate description]</code>. <code>[[adate description] substringtoindex:10]</code> возвращает строку наподобие <code>"yyyy-mm-dd"</code>, поэтому я сравнил строку со строкой, возвращенной <code>[[[nsdate date] description] substringtoindex:10]</code>.</p><p>есть ли более быстрый и/или аккуратный способ проверки?</p><p>благодарю.</p>

<p>в macos 10.9+ и ios 8+ в nscalendar/calendar есть метод, который делает именно это!</p><pre><code>- (bool)isdateintoday:(nsdate *)date </code></pre><p>так что вы бы просто сделать</p><p><strong> цель-c: </strong></p><pre><code>bool today = [[nscalendar currentcalendar] isdateintoday:date]; </code></pre><p><strong> swift 3: </strong></p><pre><code>let today = calendar.current.isdateintoday(date) </code></pre>

<p>вы можете сравнить компоненты даты:</p><pre><code>nsdatecomponents *otherday = [[nscalendar currentcalendar] components:nscalendarunitera | nscalendarunityear | nscalendarunitmonth | nscalendarunitday fromdate:adate]; nsdatecomponents *today = [[nscalendar currentcalendar] components:nscalendarunitera | nscalendarunityear | nscalendarunitmonth | nscalendarunitday fromdate:[nsdate date]]; if([today day] == [otherday day] && [today month] == [otherday month] && [today year] == [otherday year] && [today era] == [otherday era]) { //do stuff } </code></pre><p>правка:</p><p>мне больше нравится метод стефана, я думаю, что он делает более понятным и понятным утверждение if:</p><pre><code>nscalendar *cal = [nscalendar currentcalendar]; nsdatecomponents *components = [cal components:(nscalendarunitera | nscalendarunityear | nscalendarunitmonth | nscalendarunitday) fromdate:[nsdate date]]; nsdate *today = [cal datefromcomponents:components]; components = [cal components:(nscalendarunitera | nscalendarunityear | nscalendarunitmonth | nscalendarunitday) fromdate:adate]; nsdate *otherdate = [cal datefromcomponents:components]; if([today isequaltodate:otherdate]) { //do stuff } </code></pre><p>крис, я включил ваше предложение. мне пришлось посмотреть, какая была эра, поэтому для тех, кто не знает, она различает bc и ad. это, вероятно, не нужно для большинства людей, но это легко проверить и добавить определенность, поэтому я включил его. если вы идете на скорость, это, вероятно, не очень хороший метод в любом случае.</p><hr><p><strong>note</strong>как и во многих ответах по so, через 7 лет это полностью устарело. в swift сейчас просто используйте <code>.isdateintoday</code></p>

<p>это ответ на ваш вопрос, но если вы хотите напечатать nsdate с «сегодня» или «вчера», используйте функцию</p><pre><code>- (void)setdoesrelativedateformatting:(bool)b </code></pre><p>для nsdateformatter</p>

<p>я бы попытался нормализовать сегодняшнюю дату до полуночи, а вторую дату - до полуночи, а затем сравнить, совпадает ли это с nsdate.</p><p>из <a href="http://developer.apple.com/mac/library/documentation/cocoa/conceptual/datesandtimes/articles/dtcalendricalcalculations.html#//apple\_ref/doc/uid/tp40007836">пример apple</a> вот как вы нормализуете до полуночи сегодняшней даты, сделайте то же самое для второй даты и сравните:</p><pre><code>nscalendar * gregorian = [[nscalendar alloc] initwithcalendaridentifier:nsgregoriancalendar]; nsdatecomponents * components = [gregorian components: (nsyearcalendarunit|nsmonthcalendarunit|nsdaycalendarunit) fromdate:[nsdate date]]; nsdate * today = [gregorian datefromcomponents:components]; </code></pre>

<p>working<strong> расширение swift 3 & 4 </strong>предложения от catfish\_man:</p><pre><code>extension date { func istoday() -> bool { return calendar.current.isdateintoday(self) } } </code></pre>

<p>не нужно жонглировать компонентами, эпохами и прочим. </p><p>nscalendar предоставляет метод для получения начала определенной единицы времени для существующей даты.</p><p>этот код получит начало сегодняшнего дня и другую дату и сравнит это. если он оценивается как <code>nsorderedsame</code>, обе даты относятся к одному и тому же дню - так и сегодня.</p><pre><code>nsdate *today = nil; nsdate *beginningofotherdate = nil; nsdate *now = [nsdate date]; [[nscalendar currentcalendar] rangeofunit:nsdaycalendarunit startdate:&today interval:null fordate:now]; [[nscalendar currentcalendar] rangeofunit:nsdaycalendarunit startdate:&beginningofotherdate interval:null fordate:beginningofotherdate]; if([today compare:beginningofotherdate] == nsorderedsame) { //otherdate is a date in the current day } </code></pre>

<pre><code>extension nsdate { func istoday() -> bool { let cal = nscalendar.currentcalendar() var components = cal.components([.era, .year, .month, .day], fromdate:nsdate()) let today = cal.datefromcomponents(components)! components = cal.components([.era, .year, .month, .day], fromdate:self) let otherdate = cal.datefromcomponents(components)! return today.isequaltodate(otherdate) } </code></pre><p>работал для меня на swift 2.0</p>

<p>свифт версия лучшего ответа:</p><pre><code>let cal = nscalendar.currentcalendar() var components = cal.components([.era, .year, .month, .day], fromdate:nsdate()) let today = cal.datefromcomponents(components)! components = cal.components([.era, .year, .month, .day], fromdate:adate); let otherdate = cal.datefromcomponents(components)! if(today.isequaltodate(otherdate)) { //do stuff } </code></pre>

<p>вы также можете проверить временной интервал между вашей датой и текущей датой:</p><pre><code>[mydate timeintervalsincenow] </code></pre><p>это даст вам временной интервал в секундах между mydate и текущей датой/временем.</p><p> <a href="http://developer.apple.com/mac/library/documentation/cocoa/reference/foundation/classes/nsdate\_class/reference/reference.html#//apple\_ref/occ/instm/nsdate/timeintervalsincenow">ссылка на сайт</a> .</p><p>правка: примечание для всех: я хорошо знаю, что [mydate timeintervalsincenow] не однозначно определяет, является ли mydate сегодня.</p><p>я оставляю этот ответ как есть, так что если кто-то ищет что-то подобное и [mydate timeintervalsincenow] полезен, он может найти его здесь.</p>

<p>обратитесь к документации apple, озаглавленной «выполнение календарных расчетов» <a href="http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/datesandtimes/articles/dtcalendricalcalculations.html">[ссылка]</a> .</p><p>в листинге 13 на этой странице показано, что для определения количества ночей между днями вы используете:</p><pre><code>- (nsinteger)midnightsfromdate:(nsdate *)startdate todate:(nsdate *)enddate { nscalendar *calendar = [nscalendar autoupdatingcurrentcalendar]; nsinteger startday = [calendar ordinalityofunit:nsdaycalendarunit inunit:nseracalendarunit fordate:startdate]; nsinteger endday = [calendar ordinalityofunit:nsdaycalendarunit inunit:nseracalendarunit fordate:enddate]; return endday - startday; } </code></pre><p>затем вы можете определить, совпадают ли два дня, используя этот метод, и посмотреть, вернет ли он 0 или нет.</p>

<p>быстрое расширение на основе лучших ответов:</p><pre><code>extension nsdate { func istoday() -> bool { let cal = nscalendar.currentcalendar() if cal.respondstoselector("isdateintoday:") { return cal.isdateintoday(self) } var components = cal.components((.calendarunitera | .calendarunityear | .calendarunitmonth | .calendarunitday), fromdate:nsdate()) let today = cal.datefromcomponents(components)! components = cal.components((.calendarunitera | .calendarunityear | .calendarunitmonth | .calendarunitday), fromdate:self); let otherdate = cal.datefromcomponents(components)! return today.isequaltodate(otherdate) } } </code></pre>

<p>есть более простой способ, чем многие из приведенных выше ответов! </p><pre><code>nsdate *date = ... // the date you wish to test nscalendar *calendar = [nscalendar currentcalendar]; if([calendar isdateintoday:date]) { //do stuff } </code></pre>

<p>если у вас много таких сравнений дат, то вызовы <code>calendar:components:fromdate</code> начинают занимать много времени. согласно некоторому профилированию, которое я сделал, они кажутся довольно дорогими.</p><p>допустим, вы пытаетесь определить, какие из некоторого массива дат, скажем, <code>nsarray *datestocompare</code>, совпадают с определенным днем, скажем, <code>nsdate *basedate</code>, тогда вы можете использовать что-то вроде следующего (частично адаптированного из ответа выше):</p><pre><code>nsdate *basedate = [nsdate date]; nsarray *datestocompare = [nsarray arraywithobjects:[nsdate date], [nsdate datewithtimeintervalsincenow:100], [nsdate datewithtimeintervalsincenow:1000], [nsdate datewithtimeintervalsincenow:-10000], [nsdate datewithtimeintervalsincenow:100000], [nsdate datewithtimeintervalsincenow:1000000], [nsdate datewithtimeintervalsincenow:50], nil]; // determine the nsdate for midnight of the base date: nscalendar* calendar = [nscalendar currentcalendar]; nsdatecomponents* comps = [calendar components:(nsyearcalendarunit|nsmonthcalendarunit|nsdaycalendarunit) fromdate:basedate]; nsdate* themidnighthour = [calendar datefromcomponents:comps]; // set up a localized date formatter so we can see the answers are right! nsdateformatter *dateformatter = [[nsdateformatter alloc] init]; [dateformatter setdatestyle:nsdateformattermediumstyle]; [dateformatter settimestyle:nsdateformattermediumstyle]; // determine which dates in an array are on the same day as the base date: for (nsdate *date in datestocompare) { nstimeinterval interval = [date timeintervalsincedate:themidnighthour]; if (interval >= 0 && interval < 60*60*24) { nslog(@"%@ is on the same day as %@", [dateformatter stringfromdate:date], [dateformatter stringfromdate:basedate]); } else { nslog(@"%@ is not on the same day as %@", [dateformatter stringfromdate:date], [dateformatter stringfromdate:basedate]); } } </code></pre><p>результат:</p><pre><code>nov 23, 2011 1:32:00 pm is on the same day as nov 23, 2011 1:32:00 pm nov 23, 2011 1:33:40 pm is on the same day as nov 23, 2011 1:32:00 pm nov 23, 2011 1:48:40 pm is on the same day as nov 23, 2011 1:32:00 pm nov 23, 2011 10:45:20 am is on the same day as nov 23, 2011 1:32:00 pm nov 24, 2011 5:18:40 pm is not on the same day as nov 23, 2011 1:32:00 pm dec 5, 2011 3:18:40 am is not on the same day as nov 23, 2011 1:32:00 pm nov 23, 2011 1:32:50 pm is on the same day as nov 23, 2011 1:32:00 pm </code></pre>

<p>для ios7 и более ранних версий:</p><pre><code>//this is now => need that for the current date nsdate * now = [nsdate date]; nscalendar *calendar = [[nscalendar alloc] initwithcalendaridentifier:nsgregoriancalendar]; [calendar settimezone:[nstimezone systemtimezone]]; nsdatecomponents * components = [calendar components:( nsyearcalendarunit| nsmonthcalendarunit | nsdaycalendarunit | nshourcalendarunit | nsminutecalendarunit | nssecondcalendarunit) fromdate: now]; [components setminute:0]; [components sethour:0]; [components setsecond:0]; //this is today's midnight nsdate *todaysmidnight = [calendar datefromcomponents: components]; //now timeintervals since midnight => in seconds nstimeinterval todaytimeinterval = [now timeintervalsincedate: todaysmidnight]; //now timeintervals since otherdate => in seconds nstimeinterval otherdatetimeinterval = [now timeintervalsincedate: otherdate]; if(otherdatetimeinterval > todaytimeinterval) //otherdate is not in today { if((otherdatetimeinterval - todaytimeinterval) <= 86400) //86400 == a day total seconds { @"yesterday"; } else { @"earlier"; } } else { @"today"; } now = nil; calendar = nil; components = nil; todaysmidnight = nil; nslog("thank you :-)"); </code></pre>

<p>это, вероятно, может быть переработано как категория nsdate, но я использовал:</p><pre><code>// seconds per day (24h * 60m * 60s) #define ksecondsperday 86400.0f + (bool) dateistoday:(nsdate*)datetocheck { // split today into components nscalendar* gregorian = [[nscalendar alloc] initwithcalendaridentifier:nsgregoriancalendar]; nsdatecomponents* comps = [gregorian components:(nsyearcalendarunit|nsmonthcalendarunit|nsdaycalendarunit|nshourcalendarunit|nsminutecalendarunit|nssecondcalendarunit) fromdate:[nsdate date]]; // set to this morning 00:00:00 [comps sethour:0]; [comps setminute:0]; [comps setsecond:0]; nsdate* themidnighthour = [gregorian datefromcomponents:comps]; [gregorian release]; // get time difference (in seconds) between date and then nstimeinterval diff = [datetocheck timeintervalsincedate:themidnighthour]; return ( diff>=0.0f && diff<ksecondsperday ); } </code></pre><p>(однако, сравнивая две строки даты, как в первоначальном вопросе, вы чувствуете себя «чище» ..) </p>

<p>посмотрите на замечательный <code>nsdate extension</code> нашей эрики садун. очень прост в использовании. хорошо это здесь:</p><p> <a href="http://github.com/erica/nsdate-extensions">http://github.com/erica/nsdate-extensions</a> </p><p>это уже есть в этом сообщении: <a href="https://stackoverflow.com/a/4052798/362310">https://stackoverflow.com/a/4052798/362310</a> </p>

<p>правильное и безопасное решение без принудительной распаковки, работающее на swift 2.2 и до ios 8:</p><pre><code>func istoday() -> bool { let calendar = nscalendar.currentcalendar() if #available(ios 8.0, *) { return calendar.isdateintoday(self) } let todaycomponents = calendar.components([.era, .year, .month, .day], fromdate:nsdate()) let daycomponents = calendar.components([.era, .year, .month, .day], fromdate:self) guard let today = calendar.datefromcomponents(todaycomponents), day = calendar.datefromcomponents(daycomponents) else { return false } return today.compare(day) == .orderedsame } </code></pre>