2009-08-06 38 views
54

Tôi có một khoảng thời gian kéo dài nhiều năm và tôi muốn tất cả các thành phần thời gian từ năm này sang giây khác. Ý tưởng đầu tiên của tôi là số nguyên chia khoảng thời gian tính bằng giây trong một năm, trừ đi số giây đó trong tổng số giây, chia cho số giây trong một tháng, trừ số đó khỏi tổng số đang chạy và cứ như vậy.Làm cách nào để chia nhỏ NSTimeInterval thành năm, tháng, ngày, giờ, phút và giây trên iPhone?

Điều đó có vẻ phức tạp và tôi đã đọc rằng bất cứ khi nào bạn đang làm điều gì đó trông phức tạp, có thể là một phương pháp tích hợp sẵn.

Có phải không?

Tôi đã tích hợp phương thức thứ 2 của Alex vào mã của tôi.

Đó là phương thức được gọi bởi UIDatePicker trong giao diện của tôi.

NSDate *now = [NSDate date]; 
NSDate *then = self.datePicker.date; 
NSTimeInterval howLong = [now timeIntervalSinceDate:then]; 

NSDate *date = [NSDate dateWithTimeIntervalSince1970:howLong]; 
NSString *dateStr = [date description]; 
const char *dateStrPtr = [dateStr UTF8String]; 
int year, month, day, hour, minute, sec; 

sscanf(dateStrPtr, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &sec); 
year -= 1970; 

NSLog(@"%d years\n%d months\n%d days\n%d hours\n%d minutes\n%d seconds", year, month, day, hour, minute, sec); 

Khi tôi đặt chọn ngày để hẹn hò 1 năm và 1 ngày trong quá khứ, tôi nhận được:

1 năm 1 tháng 1 ngày 16 giờ 0 phút 20 giây

cách đây 1 tháng và 16 giờ. Nếu tôi đặt bộ chọn ngày thành 1 ngày trong quá khứ, tôi sẽ giảm số tiền tương tự.

Cập nhật: Tôi có một ứng dụng tính toán tuổi của bạn trong năm, cho sinh nhật của bạn (được đặt từ UIDatePicker), nhưng nó thường bị tắt. Điều này chứng minh có một sự thiếu chính xác, nhưng tôi không thể tìm ra nó đến từ đâu, phải không?

+0

Nếu bạn đặt chọn ngày để một ngày trước, bạn tắt bởi một tháng và mười sáu giờ ? –

+0

có, một tháng và mười sáu giờ. – willc2

+0

Nếu kết quả là liên tục một tháng và mười sáu giờ, bất kể bạn chọn giá trị nào, hoặc bạn trừ số đó khỏi các biến, với dịch chuyển hoặc bạn cần đánh giá lỗi đó đến từ đâu. Đoán của tôi là có điều gì đó không đúng với khoảng thời gian của bạn, nếu bạn luôn luôn đi theo số tiền đó. –

Trả lời

99

Tóm tắt Mô tả

  1. Chỉ cần một cách tiếp cận để hoàn thành câu trả lời của JBRWilkinson nhưng thêm một số mã . Nó cũng có thể cung cấp một giải pháp cho bình luận của Alex Reynolds.

  2. phương pháp sử dụng NSCalendar:

    • (NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSUInteger)opts

    • "Returns, như là một NSDateComponents đối tượng sử dụng các thành phần cụ thể, sự khác biệt giữa hai thời điểm cung cấp". (Từ tài liệu API).

  3. Tạo 2 NSDate có chênh lệch là NSTimeInterval bạn muốn chia nhỏ.(Nếu NSTimeInterval của bạn xuất phát từ việc so sánh 2 NSDate bạn không cần thực hiện bước này, và bạn thậm chí không cần NSTimeInterval, chỉ cần áp dụng ngày tháng cho phương thức NSCalendar).

  4. Nhận báo giá của bạn từ NSDateComponents

Mẫu Mã

// The time interval 
NSTimeInterval theTimeInterval = ...; 

// Get the system calendar 
NSCalendar *sysCalendar = [NSCalendar currentCalendar]; 

// Create the NSDates 
NSDate *date1 = [[NSDate alloc] init]; 
NSDate *date2 = [[NSDate alloc] initWithTimeInterval:theTimeInterval sinceDate:date1]; 

// Get conversion to months, days, hours, minutes 
NSCalendarUnit unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit; 

NSDateComponents *breakdownInfo = [sysCalendar components:unitFlags fromDate:date1 toDate:date2 options:0]; 
NSLog(@"Break down: %i min : %i hours : %i days : %i months", [breakdownInfo minute], [breakdownInfo hour], [breakdownInfo day], [breakdownInfo month]); 
+0

Mã hoạt động thực tế, trái ngược với văn bản, được đánh giá cao. – willc2

+0

Cảm ơn bạn rất vui lòng. – Martin

+5

phương pháp này có vấn đề về việc thay đổi thời gian tiết kiệm ánh sáng ban ngày, bạn sẽ gặp phải sự cố 1 giờ trực tiếp. – hokkuk

4

Chuyển đổi khoảng thời gian của bạn thành một NSDate sử dụng +dateWithIntervalSince1970, nhận các thành phần ngày tháng bằng cách sử dụng phương thức của .

SDK Reference

+4

+1. Để tiết kiệm hơn một chút cho OP, bạn không thể chuyển đổi chính xác một khoảng thời gian thành các thành phần này, bạn phải biết bạn bắt đầu từ đâu (do đó dateWithIntervalFrom1970), vì ví dụ 29 ngày là một tháng nếu bạn đang vào tháng 2 1 (ngoại trừ năm bisextile tất nhiên) nhưng không phải nếu bạn đang ở ngày 1 tháng 1 ... – fraca7

2
NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval]; 

// format: YYYY-MM-DD HH:MM:SS ±HHMM 
NSString *dateStr = [date description]; 
NSRange range; 

// year 
range.location = 0; 
range.length = 4; 
NSString *yearStr = [dateStr substringWithRange:range]; 
int year = [yearStr intValue] - 1970; 

// month 
range.location = 5; 
range.length = 2; 
NSString *monthStr = [dateStr substringWithRange:range]; 
int month = [monthStr intValue]; 

// day, etc. 
... 
0

Đây là một khả năng, một chút bụi:

NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval]; 
NSString *dateStr = [date description]; 
const char *dateStrPtr = [dateStr UTF8String]; 

// format: YYYY-MM-DD HH:MM:SS ±HHMM 
int year, month, day, hour, minutes, seconds; 
sscanf(dateStrPtr, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minutes, &seconds); 
year -= 1970; 
+0

Trong khoảng thời gian 1 giây (một giây trước), trả về "năm -1, tháng 12, ngày 31, giờ 16, phút 0, giây 1 ". – willc2

+0

Điều đó nghe giống như một con bọ. –

3

này làm việc cho tôi:

float *lenghInSeconds = 2345.234513; 
    NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:lenghInSeconds]; 
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 


    [formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]]; 

    [formatter setDateFormat:@"HH:mm:ss"]; 
    NSLog(@"%@", [formatter stringFromDate:date]); 
    [formatter release]; 

Sự khác biệt chính ở đây là bạn cần phải điều chỉnh cho múi giờ.

+1

+1 vì không quên múi giờ –

+3

-1 vì quên bất kỳ điều gì vượt quá 24 giờ sẽ không thành công – Jonny

3

Hoặc có phương pháp lớp học của tôi. Nó không xử lý nhiều năm, nhưng điều đó có thể dễ dàng được thêm vào mặc dù nó tốt hơn cho các biểu đồ thời gian nhỏ như ngày, giờ và phút. Mất số nhiều vào tài khoản và chỉ hiển thị những gì cần thiết:

+(NSString *)TimeRemainingUntilDate:(NSDate *)date { 

    NSTimeInterval interval = [date timeIntervalSinceNow]; 
    NSString * timeRemaining = nil; 

    if (interval > 0) { 

     div_t d = div(interval, 86400); 
     int day = d.quot; 
     div_t h = div(d.rem, 3600); 
     int hour = h.quot; 
     div_t m = div(h.rem, 60); 
     int min = m.quot; 

     NSString * nbday = nil; 
     if(day > 1) 
      nbday = @"days"; 
     else if(day == 1) 
      nbday = @"day"; 
     else 
      nbday = @""; 
     NSString * nbhour = nil; 
     if(hour > 1) 
      nbhour = @"hours"; 
     else if (hour == 1) 
      nbhour = @"hour"; 
     else 
      nbhour = @""; 
     NSString * nbmin = nil; 
     if(min > 1) 
      nbmin = @"mins"; 
     else 
      nbmin = @"min"; 

     timeRemaining = [NSString stringWithFormat:@"%@%@ %@%@ %@%@",day ? [NSNumber numberWithInt:day] : @"",nbday,hour ? [NSNumber numberWithInt:hour] : @"",nbhour,min ? [NSNumber numberWithInt:min] : @"00",nbmin]; 
    } 
    else 
     timeRemaining = @"Over"; 

    return timeRemaining; 
} 
0
- (NSString *)convertTimeFromSeconds:(NSString *)seconds { 

    // Return variable. 
    NSString *result = @""; 

    // Int variables for calculation. 
    int secs = [seconds intValue]; 
    int tempHour = 0; 
    int tempMinute = 0; 
    int tempSecond = 0; 

    NSString *hour  = @""; 
    NSString *minute = @""; 
    NSString *second = @""; 

    // Convert the seconds to hours, minutes and seconds. 
    tempHour = secs/3600; 
    tempMinute = secs/60 - tempHour * 60; 
    tempSecond = secs - (tempHour * 3600 + tempMinute * 60); 

    hour = [[NSNumber numberWithInt:tempHour] stringValue]; 
    minute = [[NSNumber numberWithInt:tempMinute] stringValue]; 
    second = [[NSNumber numberWithInt:tempSecond] stringValue]; 

    // Make time look like 00:00:00 and not 0:0:0 
    if (tempHour < 10) { 
     hour = [@"0" stringByAppendingString:hour]; 
    } 

    if (tempMinute < 10) { 
     minute = [@"0" stringByAppendingString:minute]; 
    } 

    if (tempSecond < 10) { 
     second = [@"0" stringByAppendingString:second]; 
    } 

    if (tempHour == 0) { 

     NSLog(@"Result of Time Conversion: %@:%@", minute, second); 
     result = [NSString stringWithFormat:@"%@:%@", minute, second]; 

    } else { 

     NSLog(@"Result of Time Conversion: %@:%@:%@", hour, minute, second); 
     result = [NSString stringWithFormat:@"%@:%@:%@",hour, minute, second]; 

    } 

    return result; 

} 
15

Mã này là ý thức về thời gian tiết kiệm ánh sáng ban ngày và những điều khó chịu khác có thể.

NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
NSDateComponents *components = [gregorianCalendar components: (NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) 
                fromDate:startDate 
                 toDate:[NSDate date] 
                options:0]; 


NSLog(@"%ld", [components year]); 
NSLog(@"%ld", [components month]); 
NSLog(@"%ld", [components day]); 
NSLog(@"%ld", [components hour]); 
NSLog(@"%ld", [components minute]); 
NSLog(@"%ld", [components second]); 
4

Từ iOS8 trở lên bạn có thể sử dụng NSDateComponentsFormatter

Nó có phương pháp để chuyển đổi chênh lệch thời gian trong thân thiện định dạng chuỗi.

NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init]; 
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull; 

NSLog(@"%@", [formatter stringFromTimeInterval:1623452]); 

này cung cấp cho các đầu ra - 2 tuần, 4 ngày, 18 giờ, 57 phút, 32 giây

Các vấn đề liên quan