NSDate yıl / ay / gün olsun


291

NSDateBaşka bir bilgi verilmeden bir nesnenin yılını / ayını / gününü nasıl alabilirim ? Muhtemelen buna benzer bir şeyle yapabileceğimin farkındayım:

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

Ama bu bir NSDateyıl / ay / gün almak kadar basit bir şey için çok fazla güçlük gibi görünüyor . başka bir çözüm var mı?


4
Ben ilk satırı "NSCalendar * cal = [[NSCalendar tahsis] initWithCalendarIdentifier: NSGregorianCalendar];" Bu soru sorulduğundan beri API'da bir değişiklik yapılmış olmalıdır.
Russell Thackston

@ futureelite7 revizyon 1'e geri döndü. Buradaki kod, tarihi amaçlar için mevcuttu ve ilk fikrimin ne olduğunun basit bir açıklamasıydı.
Richard J. Ross III

Kod artık çalışmıyor. Doğru kodu not edebilir misiniz?
futureelite7

@ futureelite7 no. Bu kod benim ilk denememin bir gösterisiydi, asla çalışmayı amaçlamıyordu. Bunun belirsiz olduğunu düşünüyorsanız, kod bloğunu çevreleyen bağlamı düzenlemekten çekinmeyin, ancak kodun kendisini düzenlemeyin. Kodun kendisini son derece güçlü bir şekilde düzenlemek istiyorsanız, lütfen bu kapsamı meta'ya götürün ve diğer modların ne söylediğini göreceğiz.
Richard J. Ross III

8
mike bu yüzden cevapları okudun, soruyu değil.
Richard J.Ross III

Yanıtlar:


615

Görünüşe göre bu benim en popüler cevabım olduğu için, biraz daha fazla bilgi içerecek şekilde düzenlemeye çalışacağım.

İsmine rağmen, NSDatekendi başına bir tarih değil, makine zamanında bir noktayı işaretler. Bir NSDateile bir yıl, ay veya gün arasında belirtilen zaman noktası arasında bir ilişki yoktur . Bunun için bir takvime başvurmanız gerekir. Zaman içinde verilen herhangi bir nokta, hangi takvime baktığınıza bağlı olarak farklı tarih bilgileri döndürür (örneğin hem Gregoryen hem de Yahudi takvimlerinde tarihler aynı değildir) ve Gregoryen takvimi, dünya - varsayıyorum - NSDateher zaman kullanması gereken biraz önyargılıyız . NSDate, neyse ki, çok daha iki taraflı.


NSCalendarBahsettiğiniz gibi, tarih ve saati almak zorunda kalacak , ancak bunu yapmanın daha basit bir yolu var:

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

Bu NSDateComponents, geçerli günün geçerli sistem takviminden gün, ay ve yılı içeren bir nesne oluşturur . ( Not: bu, kullanıcının belirlediği geçerli takvim olmak zorunda değildir , yalnızca varsayılan sistem takvimidir.)

Elbette, farklı bir takvim veya tarih kullanıyorsanız, bunu kolayca değiştirebilirsiniz. Mevcut takvimlerin ve takvim birimlerinin bir listesi NSCalendarSınıf Referansında bulunabilir . Hakkında daha fazla bilgi NSDateComponentsbulunabilir NSDateComponentsSınıf Referans .


Referans olarak, bileşenlerden tek tek erişmek NSDateComponentsoldukça kolaydır:

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

Dikkatli olmanız gerekir: NSDateComponentsbunları geçerli bilgilerle oluşturmadıkça (yani NSCalendarbu bilgileri NSCalendarUnits sağlama talebi) istediğiniz herhangi bir alan için geçerli bilgi içermez . NSDateComponentskendi başlarına hiçbir referans bilgisi içermez - bunlar sadece erişmeniz için sayıları tutan basit yapılardır. Ayrıca örneğin bir çağ almak istiyorsanız, dışarı NSDateComponents, içinden jeneratör yöntemini beslemek gerekir NSCalendarile NSCalendarUnitErabayrak.


3
Bu düzeltme, ilk satırda NSWeekCalendarUnit yerine NSDayCalendarUnit olmalıdır.
whitehawk

@Erik Hangi takvimi kullanıyorsunuz? Kod?
Itai Ferber

7
@Jonny Aldığınız sonuçlar kullandığınız takvime bağlıdır. NSCalendar'nin +currentCalendarmetodu sistem takvimi döndürür ve kullanıcının telefon Japonca veya Tay zaman moduna ayarlandığında eğer öyleyse, farklı bir yıl alırsınız. Belirli bir takvim sistemini zorlamak istiyorsanız, bir takvim oluşturun ve uygun yerel ayarla başlatın. Örneğin, bir Gregoryen takvimini zorlamak için aşağıdakileri kullanmak istersiniz:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
Itai Ferber

2
enums NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit DEPRECATED, bunun yerine NSCalendarUnitDay kullanın.
Kunal Balani

2
Uyarı: Kullanıcıya bir değer göstermeye çalışmadığınız sürece [NSCalendar currentCalendar] öğesini kullanmayın. Kullanıcıların bir Budist takvimini (şu anki yıl 2558 veya benzeri bir şey) veya başka sayıda tuhaf takvimi takip edebileceğini düşünün. Bu durumlarda uygulamanızın kırılmasını istemezsiniz. Çok özel bir nedeniniz yoksa gregoryen takvimi kullanın. Bu hatayı yakalamak zor çünkü siz ve test kullanıcılarınız varsayılan olarak gregoryen kullanabilirsiniz.
n13

51

NSDateFormatter'ı kullanarak bir NSDate'in ayrı bileşenini alabilirsiniz:

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]];

Kısaltma yerine ayın numarasını almak istiyorsanız, "MM" kullanın. Tamsayı almak istiyorsanız şunu kullanın:[myDayString intValue];


1
Bu öz ile onun üzerine genişledi . Eğlenin --- bunu kodunuza bırakabilirsiniz.
DogEatDog

Bir sözlükte arama tarihlerini kullanmak için sorunumu çözdü :) Teşekkürler!
mlunoe

1
Bu aslında her zaman beklendiği gibi% 100 çalışmıyor. Örneğin, NSDate 2013-12-31 00:00:00 +0000 ise, tarihteki gerçek sayı 2013 olsa bile biçimlendirilen tarih 2014 yılı için geri dönecektir.
margusholland

yılın gününü nasıl alabilirim, örneğin 10 Nisan şimdiki gün, bu yılın 99. günüdür ?? -
iOS Geliştirici

17

Itai'nin mükemmel (ve çalışan!) Kodunu yeniden yazmak için, örnek bir yardımcı sınıfın, belirli bir NSDate değişkeninin yıl değerini döndürmek için nasıl görüneceği .

Gördüğünüz gibi, ay veya günü almak için bu kodu değiştirmek yeterince kolaydır.

+(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;
}

(2013'te kendi temel iOS tarih fonksiyonlarımızı yazmak zorunda olduğumuza inanamıyorum ...)

Başka bir şey: iki NSDate değerini karşılaştırmak için hiçbir zaman <ve> kullanmayın.

XCode bu kodu mutlu bir şekilde kabul edecektir (herhangi bir hata veya uyarı olmadan), ancak sonuçları bir piyango. Sen gerekir NSDates karşılaştırmak için "Karşılaştırma" işlevini kullanın:

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

4
İşaretçi karşılaştırmasının sonuçları bir piyangodan uzaktır - amaçlandıkları şey için kullandığınız sürece çok iyi tanımlanmış sonuçlara sahiptirler - nesneleri değil işaretçileri karşılaştırmak.
Richard J. Ross III

Bu bir piyango olmayabilir, ancak C # DateTime çok daha sezgisel. İOS'ta, operatörden daha azı iki NSDate'i gerçekten karşılaştırmalı ... Herkes iki NSDate değişkeninin işaretleyicilerini gerçekten karşılaştırmak ister mi? En azından, XCode show kullanıcının gerçekten ne anlama geldiğini sormak için bir Uyarı gösterir.
Mike Gledhill

1
Bu sadece yazdığı dilin temellerini anlamayan tembel bir kodlayıcının bir işareti. Ve benim için ObjC nesneleri için işaretçi karşılaştırmalarının gerekli olduğu durumlar vardı - özellikle özel bir kapsayıcı ( şeyler ARC ile garipleşir).
Richard J. Ross III

1
Temelleri anlamayan tembel bir kodlayıcı olmalıyım, ama bu harika bir ipucu Mike!
Pier-Luc Gendreau

4
İşaretçi karşılaştırmaları gerekli olabilir, ancak iki tarih karşılaştırılırken çok daha az yaygın kullanım durumlarıdır. Herhangi bir programcının tarihin% 99.99'u, işaretçiler yerine tarihleri ​​karşılaştırmakla daha fazla ilgilenir. Temel olarak C # ve .NET çerçevesi, en yaygın senaryoları daha kolay hale getirmek için tasarlandı, böylece programcıları daha üretken hale getirdi ve çoğu durumda objektif-c, işleri kasıtlı olarak daha zorlu hale getiriyor gibi geliyor. Her dilin temeli hakkında 800 sayfalık bir kitap okumak için zamanınız varsa, şerefe, ancak geri kalanımızın zamanında ve bütçeye uygun uygulamaları var.
Crake

16

Swift 2.0'da:

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

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

11

Bu yanıtı yazıyorum çünkü size NSDateComponentdeğişkenlerden geri dönüş seçenekleri vermeyen ve / veya bu değişkenleri açmaya zorlayan tek yaklaşım (Swift 3 için de).

Hızlı 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)

Hızlı 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 Swift 3 eğlenceli versiyon

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)

yılın gününü nasıl alabilirim, örneğin 10 Nisan şimdiki gün, bu yılın 99. günüdür ?? -
iOS Geliştirici

Ve Gregoryen takvimi kullandığınızdan emin olun, örneğin Japon takvimi için yıl bileşeni 1 basamak döndürür ..
Flovettee

8

İOS 8'deki Yenilikler

objc

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

hızlı

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
İnanılmaz! @Yuchen Zhong
Lito

1
Parlak ! Çok daha iyi sözdizimi!
joan

4

İOS 8 ve sonraki sürümlerini hedefliyorsanız NSCalendar, bunu daha kısa bir biçimde elde etmek için yeni kolaylık yöntemlerini kullanabilirsiniz.

Önce bir tane oluşturun NSCalendarve ne NSDategerekiyorsa kullanın .

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

Bileşenleri tek tek component:fromDate:

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

Ya da, hatta daha özlü, kullanımı NSIntegeryoluyla işaretçilerigetEra:year:month:day:fromDate:

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

Daha fazla bilgi ve örnekler için iOS 8'de NSDate Manipulation Made Easy uygulamasını inceleyin . Sorumluluk reddi, yazıyı yazdım.


yılın gününü nasıl alabilirim, örneğin 10 Nisan şimdiki gün, bu yılın 99. günüdür ?? -
iOS Geliştirici

4

İOS 8.0 (ve OS X 10) itibarıyla, aşağıdaki gibi tek bir tarih bileşenini almayı basitleştirmek için bileşen yöntemini kullanabilirsiniz :

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

İşleri basitleştirmeli ve umarım bu verimli bir şekilde uygulanır.



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);

Bu bana açıkça bir tamsayı olarak yıl, ay veya gün vermiyor, bu OP'de istediğim şey. -1.
Richard

1
Richard J. Ross III: Sadece düzelttim, üzgünüm çünkü cevabım sorunuz kayboldu.
Linh Nguyen

2

İşte Swift'teki çözüm:

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

Bunu dene . . .

Kod snippet'i:

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

Cari yıl, ay, tarih verir


1

Takip etmeyi dene:

    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)
    }
}

Olarak kullanabilirsiniz

NSDate().currentDateInDayMonthYear()

Çıktı

6 March 2016

1

hızlı

İsteğe bağlı bir Dize olarak tarih öğelerini almanın daha kolay yolu.

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

bu şekilde yaparım ....

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

Okunabilir dize (gün, ay, yıl) elde etmek için şunları yapabilirsiniz:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *string = [dateFormatter stringFromDate:dateEndDate];
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.