NSDate dapatkan tahun / bulan / hari


291

Bagaimana saya bisa mendapatkan tahun / bulan / hari suatu NSDateobjek, tidak diberi informasi lain? Saya menyadari bahwa saya mungkin bisa melakukan ini dengan sesuatu yang mirip dengan ini:

NSCalendar *cal = [[NSCalendar alloc] init];
NSDateComponents *components = [cal components:0 fromDate:date];
int year = [components year];
int month = [components month];
int day = [components day];

Tapi itu tampaknya menjadi banyak kerumitan untuk sesuatu yang sederhana seperti mendapatkan NSDatetahun / bulan / hari. Apakah ada solusi yang lain?


4
Saya mengalami sedikit masalah dalam menggunakan kode ini sampai saya mengubah baris pertama menjadi "NSCalendar * cal = [[alokasi NSCalendar] initWithCalendarIdentifier: NSGregorianCalendar];" Pasti ada perubahan pada API sejak pertanyaan ini diajukan.
Russell Thackston

@ futureelite7 kembali ke revisi 1. Kode ada untuk tujuan historis, dan merupakan penjelasan sederhana tentang apa ide awal saya.
Richard J. Ross III

Kode tidak lagi berfungsi. Bisakah Anda membuat catatan dengan kode yang benar?
futureelite7

@ futureelite7 no. Kode itu menunjukkan usaha pertama saya, tidak pernah dimaksudkan untuk bekerja. Jika Anda merasa itu ambigu, silakan mengedit konteks di sekitar blok kode itu, tetapi jangan mengedit kode itu sendiri. Jika Anda merasa sangat kuat tentang pengeditan kode itu sendiri, silakan bawa penutup ini ke meta dan kita akan melihat apa yang dikatakan oleh mod lain.
Richard J. Ross III

8
@ Mike itulah sebabnya Anda membaca jawabannya, bukan pertanyaannya.
Richard J. Ross III

Jawaban:


615

Karena ini rupanya jawaban saya yang paling populer, saya akan mencoba mengeditnya agar mengandung sedikit lebih banyak informasi.

Terlepas dari namanya, NSDatedalam dan dari dirinya sendiri hanya menandai suatu titik dalam waktu mesin, bukan tanggal. Tidak ada korelasi antara titik waktu yang ditentukan oleh satu NSDatedan satu tahun, bulan, atau hari. Untuk itu, Anda harus merujuk ke kalender. Setiap titik waktu akan mengembalikan informasi tanggal yang berbeda berdasarkan pada kalender apa yang Anda lihat (tanggal tidak sama dalam kalender Gregorian dan Yahudi, misalnya), dan sementara kalender Gregorian adalah kalender yang paling banyak digunakan di dunia - saya berasumsi - kita sedikit bias yang NSDateharus selalu menggunakannya. NSDate, untungnya, jauh lebih bipartisan.


Mendapatkan tanggal dan waktu harus melalui NSCalendar, seperti yang Anda sebutkan, tetapi ada cara yang lebih sederhana untuk melakukannya:

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];

Itu menghasilkan NSDateComponentsobjek yang berisi hari, bulan, dan tahun dari kalender sistem saat ini untuk hari ini. ( Catatan: ini belum tentu kalender yang ditentukan pengguna saat ini , hanya kalender sistem default.)

Tentu saja, jika Anda menggunakan kalender atau tanggal yang berbeda, Anda dapat dengan mudah mengubahnya. Daftar unit kalender dan kalender yang tersedia dapat ditemukan di NSCalendarReferensi Kelas . Informasi lebih lanjut tentang NSDateComponentsini dapat ditemukan di NSDateComponentsReferensi Kelas .


Untuk referensi, mengakses komponen individu dari NSDateComponentsagak mudah:

NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];

Anda hanya harus berhati-hati: NSDateComponentstidak akan berisi informasi yang valid untuk bidang apa pun yang Anda minta kecuali Anda membuat mereka dengan informasi yang valid (yaitu permintaan NSCalendaruntuk memberikan informasi itu denganNSCalendarUnit s). NSDateComponentstidak mengandung informasi referensi di dalam dan tentang diri mereka sendiri - mereka hanya struktur sederhana yang menyimpan angka untuk Anda akses. Jika Anda ingin mendapatkan era, misalnya, dari NSDateComponents, Anda harus memberi makan metode generator dari NSCalendardengan NSCalendarUnitErabendera.


3
Koreksi untuk ini, baris pertama harus memiliki NSDayCalendarUnit bukan NSWeekCalendarUnit.
whitehawk

@Erik Kalender mana yang Anda gunakan? Kode?
Itai Ferber

7
@ Jonny Hasil yang Anda peroleh tergantung pada kalender yang Anda gunakan. NSCalendar's +currentCalendarmetode akan mengembalikan kalender sistem, dan jadi jika telepon pengguna diatur ke mode Jepang atau Thailand waktu, Anda akan mendapatkan tahun yang berbeda. Jika Anda ingin memaksakan sistem kalender tertentu, buat kalender dan inisialisasi dengan lokal yang tepat. Misalnya, untuk memaksakan kalender Gregorian, Anda harus menggunakan yang berikut ini:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
Itai Ferber

2
enums NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit lebih disukai daripada menggunakan NSCalendarUnitDay.
Kunal Balani

2
Peringatan: Jangan gunakan [NSCalendar currentCalendar] kecuali Anda mencoba menunjukkan nilai kepada pengguna. Pertimbangkan bahwa pengguna dapat mengikuti kalender Buddha (tahun ini adalah 2558 atau sesuatu), atau jumlah kalender ganjil lainnya. Anda tidak ingin aplikasi Anda rusak dalam hal ini. Gunakan kalender gregorian kecuali Anda memiliki alasan yang sangat spesifik untuk tidak melakukannya. Bug ini sulit ditangkap karena Anda dan penguji mungkin menggunakan gregorian sebagai default.
n13

51

Anda bisa mendapatkan komponen terpisah dari NSDate menggunakan NSDateFormatter:

NSDateFormatter *df = [[NSDateFormatter alloc] init];

[df setDateFormat:@"dd"];
myDayString = [df stringFromDate:[NSDate date]];

[df setDateFormat:@"MMM"];
myMonthString = [df stringFromDate:[NSDate date]];

[df setDateFormat:@"yy"];
myYearString = [df stringFromDate:[NSDate date]];

Jika Anda ingin mendapatkan nomor bulan alih-alih singkatan, gunakan "MM". Jika Anda ingin mendapatkan bilangan bulat, gunakan[myDayString intValue];


1
Diperluas pada miliknya dengan inti ini . Bersenang-senanglah --- Anda dapat memasukkan ini ke dalam kode Anda.
DogEatDog

Memecahkan masalah saya untuk menggunakan tanggal untuk mencari di kamus :) Terima kasih!
mlunoe

1
Ini sebenarnya tidak bekerja 100% seperti yang diharapkan sepanjang waktu. Misalnya, jika NSDate adalah 2013-12-31 00:00:00 +0000 maka tanggal yang diformat akan kembali 2014 untuk tahun, bahkan jika jumlah aktual pada tanggal tersebut adalah 2013.
margusholland

bagaimana saya bisa mendapatkan hari dalam setahun misalnya 10 April adalah hari saat ini adalah hari ke-99 tahun berjalan ?? -
Pengembang iOS

17

Hanya untuk menulis ulang kode Itai yang sangat baik (dan berfungsi!), Inilah yang akan terlihat seperti contoh kelas pembantu, untuk mengembalikan nilai tahun dari variabel NSDate yang diberikan.

Seperti yang Anda lihat, cukup mudah untuk memodifikasi kode ini untuk mendapatkan bulan atau hari.

+(int)getYear:(NSDate*)date
{
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:date];

    int year = [components year];
    int month = [components month];
    int day = [components day];

    return year;
}

(Saya tidak percaya kami harus menulis fungsi tanggal iOS dasar kami sendiri seperti ini, pada 2013 ...)

Satu hal lagi: jangan pernah gunakan <dan> untuk membandingkan dua nilai NSDate.

XCode akan dengan senang hati menerima kode tersebut (tanpa kesalahan atau peringatan), tetapi hasilnya lotere. Anda harus menggunakan fungsi "bandingkan" untuk membandingkan NSDates:

if ([date1 compare:date2] == NSOrderedDescending) {
    // date1 is greater than date2        
}

4
Hasil perbandingan pointer jauh dari lotere - mereka memiliki hasil yang sangat jelas, selama Anda menggunakannya untuk apa yang dimaksudkan untuk - membandingkan pointer, bukan objek.
Richard J. Ross III

Mungkin bukan lotere, tapi DateTime C # jauh lebih intuitif. Di iOS, operator yang kurang dari itu harus membandingkan dua NSDates ... adakah yang benar-benar ingin membandingkan pointer dari dua variabel NSDate? Paling tidak, acara XCode menunjukkan Peringatan untuk menanyakan apakah ini benar-benar yang dimaksud pengguna.
Mike Gledhill

1
Itu hanya pertanda seorang pembuat kode malas yang tidak mengerti dasar-dasar bahasa yang ditulisnya. Dan, ada beberapa situasi bagi saya di mana perbandingan pointer diperlukan untuk objek ObjC - terutama jika Anda membuat wadah khusus (meskipun segalanya menjadi lebih aneh dengan ARC).
Richard J. Ross III

1
Saya harus menjadi pembuat kode malas yang tidak mengerti dasar-dasarnya, tapi itu tip yang bagus Mike!
Pier-Luc Gendreau

4
Perbandingan pointer mungkin diperlukan tetapi mereka adalah kasus penggunaan yang jauh lebih umum ketika membandingkan dua tanggal. 99,99% dari waktu mana pun programmer akan lebih tertarik membandingkan tanggal daripada pointer. Pada dasarnya C # dan .NET framework dirancang untuk membuat skenario yang paling umum lebih mudah, sehingga membuat programmer lebih produktif, dan dalam banyak kasus objektif-c terasa seperti itu membuat hal-hal sengaja dibuat lebih sulit. Jika Anda punya waktu untuk membaca buku setebal 800 halaman tentang dasar-dasar setiap bahasa, tepuk tangan, tetapi kami semua memiliki aplikasi untuk dikirimkan tepat waktu dan sesuai anggaran.
Crake

16

Dalam Swift 2.0:

    let date = NSDate()
    let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
    let components = calendar.components([.Month, .Day], fromDate: date)

    let (month, day) = (components.month, components.day)

11

Saya menulis jawaban ini karena itu satu-satunya pendekatan yang tidak memberi Anda opsional kembali dari NSDateComponentvariabel dan / atau memaksa membuka bungkus variabel tersebut (juga untuk Swift 3).

Cepat 3

let date = Date()
let cal = Calendar.current
let year = cal.component(.year, from: date)
let month = cal.component(.month, from: date)
let day = cal.component(.day, from: date)

Cepat 2

let date = NSDate()
let cal = NSCalendar.currentCalendar()
let year = cal.component(.Year, fromDate: date)
let month = cal.component(.Month, fromDate: date)
let day = cal.component(.Day, fromDate: date)

Bonus versi menyenangkan Swift 3

let date = Date()
let component = { (unit) in return Calendar.current().component(unit, from: date) }
let year = component(.year)
let month = component(.month)
let day = component(.day)

bagaimana saya bisa mendapatkan hari dalam setahun misalnya 10 April adalah hari saat ini adalah hari ke-99 tahun berjalan ?? -
Pengembang iOS

Dan pastikan Anda menggunakan kalender Gregorian, mis. Komponen tahun untuk kalender Jepang mengembalikan 1 digit ..
Flovettee

8

Baru di iOS 8

ObjC

NSDate *date = [NSDate date];
NSInteger era, year, month, day;
[[NSCalendar currentCalendar] getEra:&era year:&year month:&month day:&day fromDate:date];

Cepat

let date = NSDate.init()
var era = 0, year = 0, month = 0, day = 0
NSCalendar.currentCalendar().getEra(&era, year:&year, month:&month, day:&day, fromDate: date)

2
Luar biasa! @Yuchen Zhong
Lito

1
Cemerlang! Sintaksnya jauh lebih baik!
joan

4

Jika Anda menargetkan iOS 8+ Anda dapat menggunakan yang baru NSCalendar metode kenyamanan untuk mencapai ini dalam format yang lebih singkat.

Pertama buat NSCalendardan gunakan apa pun NSDateyang diperlukan.

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *date = [NSDate date];

Anda dapat mengekstrak komponen satu per satu melalui component:fromDate:

NSInteger year = [calendar component:NSCalendarUnitYear fromDate:date];
NSInteger month = [calendar component:NSCalendarUnitMonth fromDate:date];
NSInteger day = [calendar component:NSCalendarUnitDay fromDate:date];

Atau, bahkan lebih ringkas, gunakan NSIntegerpointer melaluigetEra:year:month:day:fromDate:

NSInteger year, month, day;
[calendar getEra:nil year:&year month:&month day:&day fromDate:date];

Untuk informasi dan contoh lebih lanjut, lihat Manipulasi NSDate yang Dibuat Mudah di iOS 8 . Penafian, saya menulis posting.


bagaimana saya bisa mendapatkan hari dalam setahun misalnya 10 April adalah hari saat ini adalah hari ke-99 tahun berjalan ?? -
Pengembang iOS

4

Pada iOS 8.0 (dan OS X 10) Anda dapat menggunakan metode komponen untuk menyederhanakan mendapatkan komponen kencan tunggal seperti:

int year = [[NSCalendar currentCalendar] component:NSCalendarUnitYear fromDate:[NSDate date]];

Seharusnya membuat semuanya lebih sederhana dan mudah-mudahan ini diterapkan secara efisien.



2
    NSDate *currDate = [NSDate date];
    NSCalendar*       calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents* components = [calendar components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:currDate];
    NSInteger         day = [components day];
    NSInteger         month = [components month];
    NSInteger         year = [components year];
    NSLog(@"%d/%d/%d", day, month, year);

Itu jelas tidak memberi saya tahun, bulan atau hari sebagai bilangan bulat, yang saya minta di OP. -1.
Richard J. Ross III

1
Richard J. Ross III: Saya baru saja memperbaikinya, saya minta maaf karena jawaban saya hilang dari pertanyaan Anda.
Linh Nguyen

2

Inilah solusinya di Swift:

let todayDate = NSDate()
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!

// Use a mask to extract the required components. Extract only the required components, since it'll be expensive to compute all available values.
let components = calendar.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: todayDate)

var (year, month, date) = (components.year, components.month, components.day) 

2

Coba ini . . .

Cuplikan kode:

 NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
 int year = [components year];
 int month = [components month];
 int day = [components day];

Ini memberikan tahun, bulan, tanggal saat ini


1

Coba yang berikut ini:

    NSString *birthday = @"06/15/1977";
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"MM/dd/yyyy"];
    NSDate *date = [formatter dateFromString:birthday];
    if(date!=nil) {
        NSInteger age = [date timeIntervalSinceNow]/31556926;
        NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
        NSInteger day = [components day];
        NSInteger month = [components month];
        NSInteger year = [components year];

        NSLog(@"Day:%d Month:%d Year:%d Age:%d",day,month,year,age);
    }
    [formatter release];

1

Swift 2.x

extension NSDate {
    func currentDateInDayMonthYear() -> String {
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "d LLLL yyyy"
        return dateFormatter.stringFromDate(self)
    }
}

Anda dapat menggunakannya sebagai

NSDate().currentDateInDayMonthYear()

Keluaran

6 March 2016

1

Cepat

Cara yang lebih mudah untuk mendapatkan elemen tanggal sebagai String opsional.

extension Date {

  // Year 
  var currentYear: String? {
    return getDateComponent(dateFormat: "yy")
    //return getDateComponent(dateFormat: "yyyy")
  }

  // Month 
  var currentMonth: String? {
    return getDateComponent(dateFormat: "M")
    //return getDateComponent(dateFormat: "MM")
    //return getDateComponent(dateFormat: "MMM")
    //return getDateComponent(dateFormat: "MMMM")
  }


  // Day
  var currentDay: String? {
    return getDateComponent(dateFormat: "dd")
    //return getDateComponent(dateFormat: "d")
  }


  func getDateComponent(dateFormat: String) -> String? {
    let format = DateFormatter()
    format.dateFormat = dateFormat
    return format.string(from: self)
  }


}

let today = Date()
print("Current Year - \(today.currentYear)")  // result Current Year - Optional("2017")
print("Current Month - \(today.currentMonth)")  // result Current Month - Optional("7")
print("Current Day - \(today.currentDay)")  // result Current Day - Optional("10")

0

saya lakukan dengan cara ini ....

NSDate * mydate = [NSDate date];

NSCalendar * mycalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSCalendarUnit units = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;

NSDateComponents * myComponents  = [mycalendar components:units fromDate:mydate];

NSLog(@"%d-%d-%d",myComponents.day,myComponents.month,myComponents.year);

0

Untuk mendapatkan string yang dapat dibaca manusia (hari, bulan, tahun), Anda dapat melakukan:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *string = [dateFormatter stringFromDate:dateEndDate];
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.