2009-10-06 23 views
13

Tôi đang cố gắng để có được NSDate từ UIDatePicker, nhưng nó liên tục trả về cho tôi một thời gian ngày với dấu 20 giây. Làm thế nào tôi có thể tự thiết lập NSDate giây của không?Cách đặt giây thành 0 cho NSDate

Trả lời

12

NSDate không thay đổi, do đó bạn không thể sửa đổi thời gian của nó. Nhưng bạn có thể tạo một đối tượng ngày mới mà dính vào phút gần nhất:

NSTimeInterval time = floor([date timeIntervalSinceReferenceDate]/60.0) * 60.0; 
NSDate *minute = [NSDate dateWithTimeIntervalSinceReferenceDate:time]; 

Chỉnh sửa để trả lời bình luận Uli của

Ngày tham chiếu cho NSDate là 01 tháng 1 năm 2001, 00:00 GMT. Đã có hai giây nhảy vọt được thêm vào kể từ sau đó: 2005 và 2010, do đó giá trị trả về bởi [NSDate timeIntervalSinceReferenceDate] sẽ bị tắt sau hai giây.

Đây không phải là trường hợp: timeIntervalSinceReferenceDate chính xác đồng bộ với thời gian trên tường.

Khi trả lời câu hỏi tôi không đảm bảo rằng điều này thực sự đúng. Tôi chỉ giả định rằng hệ điều hành Mac sẽ behave as UNIX time (kỷ nguyên 1970): POSIX đảm bảo rằng mỗi ngày bắt đầu từ một bội số của 86.400 giây.

Nhìn vào các giá trị được trả về từ NSDate giả định này có vẻ đúng nhưng chắc chắn sẽ tốt hơn nếu tìm một tuyên bố xác định (được ghi chép) về điều đó.

+4

Điều này sẽ không hoạt động. Khoảng thời gian kể từ ngày tham chiếu không được đảm bảo là số chẵn của 60 trong một khoảng thời gian có 00 giây. Đó là số giây kể từ ngày tham chiếu, và như vậy, những giây nhảy vọt mà đôi khi được chèn vào sẽ khiến bạn tắt. Tôi nghĩ rằng bạn sẽ phải sử dụng NSCalendar để tìm ra những giây của bạn có, sau đó trừ * rằng * từ khoảng thời gian. – uliwitness

+1

Thời gian bạn nhận được có thể là một phút trong tương lai, nếu phút hiện tại vượt quá mốc 30 giây. Điều này xảy ra bởi vì vòng có thể làm tròn lên. Hãy thử với 'sàn ([ngày timeIntervalSinceReferenceDate]/60.0) * 60.0;' –

+1

@flovonderuni Tốt bắt. Các kết quả từ 'sàn' chuyển đổi cùng một lúc đồng hồ treo tường làm. Câu trả lời đã chỉnh sửa, cảm ơn! –

1

NSDate ghi lại một khoảnh khắc trong thời gian. Nếu những gì bạn muốn làm là lưu trữ một ngày cụ thể, không sử dụng NSDate. Bạn sẽ nhận được rất nhiều đau đầu bất ngờ liên quan đến múi giờ, thời gian tiết kiệm ánh sáng ban ngày e.tc.

Một giải pháp thay thế là lưu trữ ngày dưới dạng số nguyên theo định dạng chuẩn gần như ISO, như 20110915 cho ngày 15 tháng 9 năm 2011. Điều này được đảm bảo sắp xếp theo cùng cách như NSDate sẽ sắp xếp.

10

Bạn không thể thao tác trực tiếp NSTimeInterval vì đó là khoảng cách tính bằng giây kể từ ngày tham chiếu, không được đảm bảo là giây thứ hai khi được chia cho 60. Sau khi tất cả, giây nhảy vọt có thể là chèn vào để điều chỉnh sự khác biệt giữa thời gian mặt trời và UTC. Mỗi giây nhảy vọt sẽ ném bạn đi bằng 1. Những gì tôi làm để sửa số giây của ngày của tôi thành 0 là:

NSDate    * startDateTime = [NSDate date]; 
NSDateComponents * startSeconds = [[NSCalendar currentCalendar] components: NSSecondCalendarUnit fromDate: startDateTime]; 

startDateTime = [NSDate dateWithTimeIntervalSinceReferenceDate: [startDateTime timeIntervalSinceReferenceDate] -[startSeconds second]]; 

Điều này sẽ mất vài giây. Tôi đoán một cách thậm chí sạch sẽ được sử dụng -dateByAddingComponents:

NSDate    * startDateTime = [NSDate date]; 
NSDateComponents * startSeconds = [[NSCalendar currentCalendar] components: NSSecondCalendarUnit fromDate: startDateTime]; 
[startSeconds setSecond: -[startSeconds second]]; 

startDateTime = [[NSCalendar currentCalendar] dateByAddingComponents: startSeconds toDate: startDateTime options: 0]; 

Bằng cách đó bạn sẽ được bảo đảm rằng bất cứ điều gì đặc biệt điều -dateByAddingComponents: chăm sóc được hạch toán là tốt.

+1

Tôi tin rằng yêu cầu của bạn về số giây nhảy vọt ảnh hưởng đến 'timeIntervalSinceReferenceDate' là không đúng sự thật. Trong khi Hướng dẫn lập trình ngày và giờ của Apple không xác định rõ ràng hành vi, POSIX thực hiện điều đó cho thời gian UNIX: Các giây nhuận được bỏ qua (xem http://en.wikipedia.org/wiki/Unix_time). Có vẻ như điều này cũng đúng với Cocoa. –

+1

Một ý nghĩ khác: Cả hai giải pháp được đề xuất của bạn không tính đến các phần nhỏ trong một giây. Bạn tính số giây (số nguyên) và trừ chúng khỏi ngày ban đầu. Kết quả đề cập đến một thời gian với 0 giây nhưng không phải là mili giây, mà là một chút lẻ. –

2

Mặc dù đây là câu hỏi cũ và Uli đã đưa ra câu trả lời "đúng", giải pháp đơn giản nhất IMHO là chỉ trừ giây từ ngày, như được lấy từ lịch. Tâm trí rằng điều này vẫn có thể để lại mili giây tại chỗ.

NSDate *date = [NSDate date]; 
NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSCalendarUnitSecond 
                 fromDate:date]; 
date = [date dateByAddingTimeInterval:-comp.second]; 
1

Đây là một phần mở rộng để làm điều này trong Swift:

extension NSDate { 
    func truncateSeconds() -> NSDate { 
     let roundedTime = floor(self.timeIntervalSinceReferenceDate/60) * 60 
     return NSDate(timeIntervalSinceReferenceDate: roundedTime) 
    } 
} 
0

Đây là một phần mở rộng Swift cho bất cứ ai quan tâm:

extension Date { 
    public mutating func floorSeconds() { 
     let calendar = Calendar.current 
     let components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: self) 
     self = calendar.date(from: components) ?? self // you can handle nil however you choose, probably safe to force unwrap in most cases anyway 
    } 
} 

Ví dụ sử dụng:

let date = Date() 
date.floorSeconds() 

Sử dụng DateComponents mạnh hơn nhiều so với việc thêm khoảng thời gian vào một ngày.

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