المقارنة بين اثنين من NSDates و تجاهل عنصر الوقت

StackOverflow https://stackoverflow.com/questions/1854890

  •  13-09-2019
  •  | 
  •  

سؤال

ما هو الأكثر كفاءة/الطريقة الموصى بها من المقارنة بين اثنين من NSDates?وأود أن تكون قادرة على معرفة إذا كان كل التواريخ في نفس اليوم ، بغض النظر عن الوقت و قد بدأت كتابة بعض التعليمات البرمجية التي تستخدم timeIntervalSinceDate:طريقة داخل NSDate فئة يحصل على عدد صحيح من هذه القيمة مقسوما على عدد الثواني في اليوم.هذا يبدو ينضب طويلة و أنا أشعر أن أنا في عداد المفقودين شيء واضح.

مدونة أحاول أن الإصلاح هو:

if (!([key compare:todaysDate] == NSOrderedDescending))
{
    todaysDateSection = [eventSectionsArray count] - 1;
}

حيث مفتاح todaysDate هي NSDate الكائنات todaysDate هو إنشاء باستخدام:

NSDate *todaysDate = [[NSDate alloc] init];

تحياتي

ديف

هل كانت مفيدة؟

المحلول

قمت بتعيين الوقت في تاريخ إلى 00:00:00 قبل القيام بالمقارنة:

unsigned int flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSCalendar* calendar = [NSCalendar currentCalendar];

NSDateComponents* components = [calendar components:flags fromDate:date];

NSDate* dateOnly = [calendar dateFromComponents:components];

// ... necessary cleanup

ثم يمكنك مقارنة قيم التاريخ. انظر نظرة عامة في الوثائق المرجعية.

نصائح أخرى

أنا مندهش من عدم وجود إجابات أخرى هذا الخيار للحصول على تاريخ "بداية اليوم" للكائنات:

[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date1 interval:NULL forDate:date1];
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date2 interval:NULL forDate:date2];

الذي يحدد date1 و date2 إلى بداية أيام كل منهم. إذا كانوا متساوين، فهي في نفس اليوم.

أو هذا الخيار:

NSUInteger day1 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit: forDate:date1];
NSUInteger day2 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:date2];

الذي يحدد day1 و day2 إلى القيم التعسفية إلى حد ما يمكن مقارنتها. إذا كانوا متساوين، فهي في نفس اليوم.

هناك طريقة جديدة تم تقديمها إلى Nscalendar مع IOS 8 التي تجعل هذا أسهل بكثير.

- (NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit NS_AVAILABLE(10_9, 8_0);

قمت بتعيين الحبيبية لوحدة (وحدات) تلك المسألة. هذا يتجاهل جميع الوحدات الأخرى والحدود مقارنة مع تلك المحددة.

بالنسبة إلى iOS8 والإصدارات الأحدث، تحقق مما إذا كانت التواريخ تحدثتين في نفس اليوم هي بسيطة مثل:

[[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2]

يرى توثيق

هذا اختصار من جميع الإجابات:

NSInteger interval = [[[NSCalendar currentCalendar] components: NSDayCalendarUnit
                                                                  fromDate: date1
                                                                    toDate: date2
                                                                   options: 0] day];
    if(interval<0){
       //date1<date2
    }else if (interval>0){
       //date2<date1
    }else{
       //date1=date2
    }

لقد استخدمت نهج دنكان ج، لقد قمت بإصلاح بعض الأخطاء التي صنعها

-(NSInteger) daysBetweenDate:(NSDate *)firstDate andDate:(NSDate *)secondDate { 

    NSCalendar *currentCalendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [currentCalendar components: NSDayCalendarUnit fromDate: firstDate toDate: secondDate options: 0];

    NSInteger days = [components day];

    return days;
}

يمكنني استخدام طريقة Util هذه:

-(NSDate*)normalizedDateWithDate:(NSDate*)date
{
   NSDateComponents* components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
                                              fromDate: date];
   return [calendar_ dateFromComponents:components]; // NB calendar_ must be initialized
}

(من الواضح أنك تحتاج إلى أن يكون لديك إيفار calendar_ تحتوي على an. NSCalendar.)

باستخدام هذا، من السهل التحقق مما إذا كان التاريخ هو اليوم مثل هذا:

[[self normalizeDate:aDate] isEqualToDate:[self normalizeDate:[NSDate date]]];

([NSDate date] إرجاع التاريخ والوقت الحالي.)

هذا بالطبع يشبه إلى ما يقترحه غريغوري. عيب هذا النهج هو أنه يميل إلى خلق الكثير من المؤقت NSDate أشياء. إذا كنت ستعالج الكثير من التواريخ، فسوف أوصي باستخدام طريقة أخرى، مثل مقارنة المكونات مباشرة، أو العمل معها NSDateComponents الكائنات بدلا من NSDates.

الجواب أبسط من الجميع يجعلها. nscalendar لديه طريقة

components:fromDate:toDate:options

تتيح لك هذه الطريقة حساب الفرق بين تاريخين باستخدام أي وحدات تريدها.

حتى اكتب طريقة مثل هذا:

-(NSInteger) daysBetweenDate: (NSDate *firstDate) andDate: (NSDate *secondDate)
{
  NSCalendar *currentCalendar = [NSCalendar currentCalendar];
  NSDateComponents components* = [currentCalendar components: NSDayCalendarUnit
    fromDate: firstDate 
    toDate: secondDate
    options: 0];

  NSInteger days = [components days];
  return days;
}

إذا عودة الأسلوب أعلاه صفر، فإن التواريخ هي في نفس اليوم.

من iOS 8.0 فصاعدا، يمكنك استخدام:

NSCalendar *calendar = [NSCalendar currentCalendar];
NSComparisonResult dateComparison = [calendar compareDate:[NSDate date] toDate:otherNSDate toUnitGranularity:NSCalendarUnitDay];

إذا كانت النتيجة مثل NSORDEREDESCESTENDESSENDESSENT، فستكون الآخر قبل [تاريخ NSDate] من حيث الأيام.

أنا لا أرى هذه الطريقة في وثائق NSCALENDER لكنها في iOS 7.1 إلى اختلافات IOS 8.0 API

للمطورين الترميز في SWIFT 3

if(NSCalendar.current.isDate(selectedDate, inSameDayAs: NSDate() as Date)){
     // Do something
}

مع سويفت 3, وفقا للاحتياجات الخاصة بك ، يمكنك اختيار واحد من اثنين من الأنماط التالية من أجل حل مشكلتك.


#1.باستخدام compare(_:to:toGranularity:) طريقة

Calendar لديه طريقة تسمى compare(_:​to:​to​Granularity:​). compare(_:​to:​to​Granularity:​) وقد الإعلان التالي:

func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult

يقارن إعطاء مواعيد وصولا إلى إعطاء مكون الإبلاغ عنها ordered​Same إذا كانت هي نفسها في مكون كل مكونات أكبر ، وإلا إما ordered​Ascending أو ordered​Descending.

الملعب البرمجية أدناه يظهر الساخنة لاستخدامها:

import Foundation

let calendar = Calendar.current
let date1 = Date() // "Mar 31, 2017, 2:01 PM"
let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM"
let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM"

/* Compare date1 and date2 */
do {
    let comparisonResult = calendar.compare(date1, to: date2, toGranularity: .day)
    switch comparisonResult {
    case ComparisonResult.orderedSame:
        print("Same day")
    default:
        print("Not the same day")
    }
    // Prints: "Not the same day"
}

/* Compare date1 and date3 */
do {
    let comparisonResult = calendar.compare(date1, to: date3, toGranularity: .day)
    if case ComparisonResult.orderedSame = comparisonResult {
        print("Same day")
    } else {
        print("Not the same day")
    }
    // Prints: "Same day"
}

#2.باستخدام dateComponents(_:from:to:)

Calendar لديه طريقة تسمى dateComponents(_:from:to:). dateComponents(_:from:to:) وقد الإعلان التالي:

func dateComponents(_ components: Set<Calendar.Component>, from start: Date, to end: Date) -> DateComponents

ترجع الفرق بين تاريخين.

الملعب البرمجية أدناه يظهر الساخنة لاستخدامها:

import Foundation

let calendar = Calendar.current
let date1 = Date() // "Mar 31, 2017, 2:01 PM"
let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM"
let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM"

/* Compare date1 and date2 */
do {
    let dateComponents = calendar.dateComponents([.day], from: date1, to: date2)
    switch dateComponents.day {
    case let value? where value < 0:
        print("date2 is before date1")
    case let value? where value > 0:
        print("date2 is after date1")
    case let value? where value == 0:
        print("date2 equals date1")
    default:
        print("Could not compare dates")
    }
    // Prints: date2 is before date1
}

/* Compare date1 and date3 */
do {
    let dateComponents = calendar.dateComponents([.day], from: date1, to: date3)
    switch dateComponents.day {
    case let value? where value < 0:
        print("date2 is before date1")
    case let value? where value > 0:
        print("date2 is after date1")
    case let value? where value == 0:
        print("date2 equals date1")
    default:
        print("Could not compare dates")
    }
    // Prints: date2 equals date1
}
int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24);
if (interval!=0){
   //not the same day;
}

كان الحل الخاص بي تحويلتين مع NSDateFormatter:

    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"yyyyMMdd"];
    [dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];

    NSDate *today = [NSDate dateWithTimeIntervalSinceNow:0];
    NSString *todayString=[dateFormat stringFromDate:today];
    NSDate *todayWithoutHour=[dateFormat dateFromString:todayString];

    if ([today compare:exprDate] == NSOrderedDescending)
    {
       //do  
    }

الوثائق المتعلقة nsdate. يشير إلى أن compare: و isEqual: سوف تقوم الأساليب بإجراء مقارنة أساسية وطلب النتائج، وإن كان لا يزال عاملا في الوقت المناسب.

ربما أبسط طريقة لإدارة المهمة ستكون لإنشاء جديد isToday طريقة لتأثير ما يلي:

- (bool)isToday:(NSDate *)otherDate
{
    currentTime = [however current time is retrieved]; // Pardon the bit of pseudo-code

    if (currentTime < [otherDate timeIntervalSinceNow])
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

هذا قط قبيح للغاية إلى الجلد، ولكن هنا طريقة أخرى للقيام بذلك. لا أقول إنه أنيق، ولكن ربما تكون أقرب ما يمكن الحصول عليه مع دعم التاريخ / الوقت في نظام التشغيل iOS.

bool isToday = [[NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle] isEqualToString:[NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle]];
NSUInteger unit = NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit;
NSDateComponents *comp = [cal components:unit
                                fromDate:nowDate
                                  toDate:setDate
                                 options:0];

NSString *dMonth;
dMonth = [NSString stringWithFormat:@"%02ld",comp.month];
NSString *dDay;
dDay = [NSString stringWithFormat:@"%02ld",comp.day + (comp.hour > 0 ? 1 : 0)];

مقارنة ساعة وكذلك لإصلاح الفرق 1

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top