2014-02-16 2 views
1

저는 아직 iOS에 익숙하지 않고 NSDate에 조금 어려움을 겪고 있습니다. 내가 그 일정 기간의 시작 및 종료 날짜를 원하는 CostPeriod에 따라로케일 설정 등을 고려한 일부 NSDate 질문

CostPeriodDaily 
CostPeriodWeekly 
CostPeriodMonthly 
CostPeriodSemiAnnually 
CostPeriodAnnually 

: 기본적으로 나는 특정 내 응용 프로그램에서 CostPeriods 있습니다. CostPeriodDaily는 당연히 (즉 오늘부터) 16.Feb 2014 00:00:00 (현지 시간) - 16.Feb 2014 23:59:59 (현지 시간)입니다. 01.Feb 2014 0시 0분 0초에서 것이다 월 - 28.Feb 2014 23시 59분 59초 등

나는 처음 두 구체적인 질문이 있습니다

  1. NSWeekdayCalendarUnit : 1 항상 일요일 7을 토요일? 상관없이 로케일이 설정되어 있습니까?
  2. 내 종료일 (다음 코드와 같이)을 NSLog로 지정하거나 시작일 인 경우 보통 GMT + 1 시간대에 살고 있기 때문에 날짜는 23:00:00입니다. 이 올바른지?

    • :-)
    • 내 endDate가 함수에 지금

그리고 , 두 개의 추가 질문이 일반적으로이 기능을 확인인가 아니면 특정 로케일 설정에 따라 몇 가지 문제로 실행됩니다?

  • My CostPeriodWeekly 케이스가 오늘 잘못된 날짜 2014-02-15 23:00:00 +0000을 표시합니다. 왜 그런지 몰라 ...?
  • + (있는 NSDate *) endDateForCurrentCostPeriod (CostPeriod) costPeriod { NSCalendar 양력 * = [NSCalendar의 ALLOC] initWithCalendarIdentifier : NSGregorianCalendar];

    NSDateComponents *todayComponents = 
    [gregorian components:(NSDayCalendarUnit | NSWeekdayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:[NSDate date]]; 
    NSRange daysOfCurrentMonth = [gregorian rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]]; 
    
    
    NSDateComponents *endDateComponents = [[NSDateComponents alloc] init]; 
    
    switch (costPeriod) { 
        case CostPeriodDaily: 
         [endDateComponents setDay:[todayComponents day]]; 
         [endDateComponents setMonth:[todayComponents month]]; 
         [endDateComponents setYear:[todayComponents year]]; 
         break; 
    
        case CostPeriodWeekly: 
         //Weekday 1 = sunday, 2 = monday 
         if([todayComponents weekday] == 1){ 
          //Sunday -> do nothing, we have the end date 
          [endDateComponents setDay:[todayComponents day]]; 
          [endDateComponents setMonth:[todayComponents month]]; 
          [endDateComponents setYear:[todayComponents year]]; 
    
         } else { 
          // all other days of current week, so 8- weekday (if Friday: 8 - 6 = + 2 -> Sunday) 
          NSDateComponents *componentsToAdd = [[NSDateComponents alloc] init]; 
          [componentsToAdd setDay: 8 - [todayComponents weekday]]; 
          NSDate *endOfWeek = [gregorian dateByAddingComponents:componentsToAdd 
                       toDate:[NSDate date] options:0]; 
    
          NSDateComponents *endOfWeekComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:endOfWeek]; 
    
          [endDateComponents setDay:[endOfWeekComponents day]]; 
          [endDateComponents setMonth:[endOfWeekComponents month]]; 
          [endDateComponents setYear:[endOfWeekComponents year]]; 
         } 
         break; 
    
        case CostPeriodMonthly: 
         [endDateComponents setDay:daysOfCurrentMonth.length]; 
         [endDateComponents setMonth:[todayComponents month]]; 
         [endDateComponents setYear:[todayComponents year]]; 
         break; 
    
        case CostPeriodSemiAnnually: 
         [endDateComponents setYear:[todayComponents year]]; 
    
         if([todayComponents month] <= 6){ 
          [endDateComponents setDay:30]; 
          [endDateComponents setMonth:6]; 
         } else { 
          [endDateComponents setDay:31]; 
          [endDateComponents setMonth:12]; 
         } 
         break; 
    
        case CostPeriodAnnually: 
         [endDateComponents setDay:31]; 
         [endDateComponents setMonth:12]; 
         [endDateComponents setYear:[todayComponents year]]; 
         break; 
    
        default: 
         [endDateComponents setDay:daysOfCurrentMonth.length]; 
         [endDateComponents setMonth:[todayComponents month]]; 
         [endDateComponents setYear:[todayComponents year]]; 
         break; 
    } 
    
    NSDate *endDate = [gregorian dateFromComponents:endDateComponents]; 
    return endDate; 
    

    }

    답변

    2

    NSWeekdayCalendarUnit : 항상 일 일요일, 7 토요일인가? 어떤 로케일이 설정 되더라도 상관 없습니까?

    맞습니다. 그렇다고해서 1 = 일요일이 항상주의 첫날로 간주됩니다. NSCalendar에는 firstWeekDay 메서드가 있고 이며 로캘에 따라 다릅니다. 나는 (다음 코드와 같이) 내 endDate가를 NSLog 경우

    (. 예를 들어, 독일에서 월요일는주의 최초의 날) 또는 보통 날짜 : 00 ~ 23 : 00입니다 시작 날짜 : 00 시간대에 살고 있기 때문에 00시에 GMT + 1. 이 올바른지?

    맞습니다.

    이 기능은 일반적으로 좋습니까? 아니면 특정 로캘 설정에 따라 몇 가지 문제가 있습니다. ?

    당신의 방법은 지나치게 복잡해 보입니다.사용할 수있는 기간을 결정하려면

    NSDate *now = [NSDate date]; 
    NSCalendar *cal = [NSCalendar currentCalendar]; 
    NSDate *startOfPeriod, *endOfPeriod; 
    NSTimeInterval lengthOfPeriod; 
    
    NSCalendarUnit unit = NSDayCalendarUnit; // or NSWeekCalendarUnit, NSMonthCalendarUnit, ... 
    [cal rangeOfUnit:unit startDate:&startOfPeriod interval:&lengthOfPeriod forDate:now]; 
    endOfPeriod = [startOfPeriod dateByAddingTimeInterval:lengthOfPeriod] 
    

    로캘에 따라 올바르게 작동해야합니다. 주 여기에 월요일에 시작하기 때문에 오늘 의 현재 일주일 동안 독일 (2월 16일 (일요일))는 결과를

    startOfPeriod = 2014-02-10 00:00:00 CET 
    endOfPeriod = 2014-02-17 00:00:00 CET 
    

    을 줄 것이라고. (그래서 실제로 endOfPeriod는 최종 기간의 하지만 다음 기간이 시작되지 않습니다.)이 반년 동안

    다음과 같이 진행할 수 있도록 더, NSCalendarUnit 해당이없는 :

    NSDate *now = [NSDate date]; 
    NSCalendar *cal = [NSCalendar currentCalendar]; 
    
    // Compute start and end of the current year (as above): 
    NSDate *startOfYear, *endOfYear; 
    NSTimeInterval lengthOfYear; 
    NSCalendarUnit unit = NSYearCalendarUnit; 
    [cal rangeOfUnit:unit startDate:&startOfYear interval:&lengthOfYear forDate:now]; 
    endOfYear = [startOfYear dateByAddingTimeInterval:lengthOfYear]; 
    
    // Compute middle of the year: 
    NSDateComponents *halfYear = [[NSDateComponents alloc] init]; 
    NSRange range = [cal rangeOfUnit:NSMonthCalendarUnit inUnit:NSYearCalendarUnit forDate:now]; 
    halfYear.month = range.length/2; 
    NSDate *middleOfYear = [cal dateByAddingComponents:halfYear toDate:startOfYear options:0]; 
    
    // Compare current date with middle of the year and set start/end of period: 
    NSDate *startOfPeriod, *endOfPeriod; 
    if ([now compare:middleOfYear] == NSOrderedAscending) { 
        startOfPeriod = startOfYear; 
        endOfPeriod = middleOfYear; 
    } else { 
        startOfPeriod = middleOfYear; 
        endOfPeriod = endOfYear; 
    } 
    

    편집 : 이것에 마틴의 도움으로 변경 다. 작동하지만, 종료 날짜 + 일일 1시간 필요성에 대해 여전히 혼란 ...

    + (NSDate *)startDateForCostPeriod:(CostPeriod)costPeriod withDate:(NSDate *)date 
    { 
        NSCalendar *calender = [NSCalendar currentCalendar]; 
        NSDate *startOfPeriod; 
        NSTimeInterval lengthOfPeriod; 
        //If unit is not initialized here, semi annual throws always a caution message since no unit is initialized there 
        NSCalendarUnit unit = NSMonthCalendarUnit; 
    
        //For the SemiAnnual period we need date components 
        NSDateComponents *todayComponents = 
        [calender components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:date]; 
        NSDateComponents *startDateComponents = [[NSDateComponents alloc] init]; 
    
        switch (costPeriod) { 
         case CostPeriodDaily: 
          unit = NSDayCalendarUnit; 
          break; 
    
         case CostPeriodWeekly: 
          unit = NSWeekCalendarUnit; 
          break; 
    
         case CostPeriodMonthly: 
          unit = NSMonthCalendarUnit; 
          break; 
    
         case CostPeriodSemiAnnually: 
          [startDateComponents setDay:1]; 
          [startDateComponents setYear:[todayComponents year]]; 
    
          if([todayComponents month] <= 6){ 
           [startDateComponents setMonth:1]; 
          } else { 
           [startDateComponents setMonth:7]; 
          } 
          break; 
    
         case CostPeriodAnnually: 
          unit = NSYearCalendarUnit; 
          break; 
    
         default: 
          unit = NSMonthCalendarUnit; 
          break; 
        } 
    
        if(costPeriod != CostPeriodSemiAnnually){ 
         [calender rangeOfUnit:unit startDate:&startOfPeriod interval:&lengthOfPeriod forDate:date]; 
         return startOfPeriod; 
        } else { 
         return [calender dateFromComponents:startDateComponents]; 
        } 
    } 
    
    + (NSDate *)endDateForCostPeriod:(CostPeriod)costPeriod withDate:(NSDate *)date 
    { 
        NSCalendar *calender = [NSCalendar currentCalendar]; 
        NSDate *startOfPeriod; 
        NSTimeInterval lengthOfPeriod; 
        //If unit is not initialized here, semi annual throws always a caution message since no unit is initialized there 
        NSCalendarUnit unit = NSMonthCalendarUnit; 
    
        //For the SemiAnnual period we need date components 
        NSDateComponents *todayComponents = 
        [calender components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:date]; 
        NSDateComponents *endDateComponents = [[NSDateComponents alloc] init]; 
    
        switch (costPeriod) { 
         case CostPeriodDaily: 
          unit = NSDayCalendarUnit; 
          break; 
    
         case CostPeriodWeekly: 
          unit = NSWeekCalendarUnit; 
          break; 
    
         case CostPeriodMonthly: 
          unit = NSMonthCalendarUnit; 
          break; 
    
         case CostPeriodSemiAnnually: 
          [endDateComponents setYear:[todayComponents year]]; 
    
          if([todayComponents month] <= 6){ 
           [endDateComponents setDay:30]; 
           [endDateComponents setMonth:6]; 
          } else { 
           [endDateComponents setDay:31]; 
           [endDateComponents setMonth:12]; 
          } 
          break; 
    
         case CostPeriodAnnually: 
          unit = NSYearCalendarUnit; 
          break; 
    
         default: 
          unit = NSMonthCalendarUnit; 
          break; 
        } 
    
        if(costPeriod != CostPeriodSemiAnnually){ 
         [calender rangeOfUnit:unit startDate:&startOfPeriod interval:&lengthOfPeriod forDate:date]; 
         return [startOfPeriod dateByAddingTimeInterval:lengthOfPeriod]; 
        } else { 
         //somehow if you take the date without a time it is always 1 day and 1 hour before. i.e. 16.2.2014 is 15.2.2014 22:00:00 
         //thats why you need to add 1 day and 1 hour! 
         NSDate *endDate = [calender dateFromComponents:endDateComponents]; 
         NSDateComponents *componentsToAdd = [[NSDateComponents alloc] init]; 
         [componentsToAdd setDay: 1]; 
         [componentsToAdd setHour: 1]; 
         endDate = [calender dateByAddingComponents:componentsToAdd 
                  toDate:endDate options:0]; 
    
         return endDate; 
        } 
    } 
    
    +0

    고마워 마틴. 내가 정확히 당신이 방법은 지역 작동 이해한다면, 월요일 또는 일요일에 상관없이 등 어떤 시간대, 일주일의 첫날에 상관없이없는 경우는? 그리고이 접근 방식으로 일정 기간의 시작 날짜를 얻는 방법을 보여 주시겠습니까? – MichiZH

    +0

    @MichiZH : 시작 날짜는 이미 해당 코드로 계산됩니다. 이것은'startDate : & startOfPeriod' 인수에서 조금 숨겨져 있습니다. 네, 로케일과 시간대에 따라 올바른 결과를 제공해야합니다. –

    +0

    다시 한번 고마워요. 내 응용 프로그램에서 지금을 다할 것입니다 :-) – MichiZH