NSDate รับปี / เดือน / วัน


291

ฉันจะรับปี / เดือน / วันของNSDateวัตถุโดยไม่มีข้อมูลอื่นได้อย่างไร ฉันรู้ว่าฉันอาจทำสิ่งนี้ด้วยสิ่งที่คล้ายกับสิ่งนี้:

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

แต่ดูเหมือนจะเป็นเรื่องยุ่งยากสำหรับบางสิ่งที่ง่ายพอ ๆ กับการได้NSDateปี / เดือน / วัน มีวิธีอื่นไหม


4
ฉันมีปัญหาเล็กน้อยในการใช้รหัสนี้จนกว่าฉันจะเปลี่ยนบรรทัดแรกเป็น "NSCalendar * cal = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];" ต้องมีการเปลี่ยนแปลง API เนื่องจากคำถามนี้ถูกถาม
รัสเซล Thackston

@ futureelite7 ย้อนกลับไปสู่การแก้ไข 1. รหัสมีไว้เพื่อจุดประสงค์ทางประวัติศาสตร์และเป็นคำอธิบายง่ายๆเกี่ยวกับความคิดเริ่มต้นของฉัน
Richard J. Ross III 3

รหัสไม่ทำงานอีกต่อไป คุณสามารถจดบันทึกรหัสที่ถูกต้องได้หรือไม่?
futureelite7

@ futureelite7 หมายเลข รหัสนั้นแสดงให้เห็นถึงความพยายามครั้งแรกของฉันมันไม่เคยตั้งใจจะทำงาน หากคุณรู้สึกว่ามันคลุมเครืออย่าลังเลที่จะแก้ไขบริบทที่ล้อมรอบบล็อกโค้ดนั้น แต่อย่าแก้ไขโค้ดเอง หากคุณรู้สึกอย่างมากเกี่ยวกับการแก้ไขโค้ดเองกรุณานำการรายงานนี้ไปที่เมตาและเราจะเห็นว่า mods อื่น ๆ มีอะไรบ้าง
Richard J. Ross III 3

8
@ ไมค์นั่นเป็นเหตุผลที่คุณอ่านคำตอบไม่ใช่คำถาม
Richard J. Ross III

คำตอบ:


615

เนื่องจากนี่เป็นคำตอบที่ได้รับความนิยมมากที่สุดของฉันฉันจะพยายามแก้ไขเพื่อให้มีข้อมูลเพิ่มเติมเล็กน้อย

แม้จะมีชื่อNSDateของตัวมันเองและในตัวของมันเองเพียงทำเครื่องหมายจุดในเวลาที่เครื่องไม่ได้เป็นวันที่ ไม่มีความสัมพันธ์กันระหว่างเวลาที่กำหนดโดยNSDatea และปีเดือนหรือวัน เพื่อที่คุณจะต้องอ้างถึงปฏิทิน เวลาใดก็ตามที่ระบุจะส่งคืนข้อมูลวันที่ที่แตกต่างกันตามปฏิทินที่คุณกำลังดู (วันที่จะไม่เหมือนกันทั้งในปฏิทินเกรโกเรียนและยิวเช่น) และในขณะที่ปฏิทินเกรกอเรียนเป็นปฏิทินที่ใช้กันอย่างแพร่หลายที่สุดใน โลก - ฉันสมมติว่า - เรามีอคติเล็กน้อยที่NSDateควรใช้มันเสมอ NSDateโชคดีที่มันเป็นพรรคสองฝ่าย


การรับวันที่และเวลาจะต้องผ่านNSCalendarตามที่คุณพูดถึง แต่มีวิธีที่ง่ายกว่าในการทำสิ่งนี้:

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

ที่สร้างNSDateComponentsวัตถุที่มีวันเดือนและปีจากปฏิทินระบบปัจจุบันสำหรับวันปัจจุบัน ( หมายเหตุ:นี่ไม่จำเป็นต้องเป็นปฏิทินที่ผู้ใช้ระบุในปัจจุบันแต่เป็นเพียงระบบเริ่มต้น)

แน่นอนถ้าคุณใช้ปฏิทินหรือวันที่อื่นคุณสามารถเปลี่ยนได้อย่างง่ายดาย รายการปฏิทินที่มีอยู่และหน่วยปฏิทินสามารถพบได้ในการอ้างอิงระดับNSCalendar ข้อมูลเพิ่มเติมเกี่ยวกับNSDateComponentsสามารถพบได้ในการอ้างอิงระดับNSDateComponents


สำหรับการอ้างอิงการเข้าถึงแต่ละองค์ประกอบจากNSDateComponentsค่อนข้างง่าย:

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

คุณต้องระวัง: NSDateComponentsจะไม่มีข้อมูลที่ถูกต้องสำหรับเขตข้อมูลใด ๆ ที่คุณขอเว้นแต่คุณจะสร้างข้อมูลที่ถูกต้องนั้นขึ้นมา (เช่นการร้องขอNSCalendarเพื่อให้ข้อมูลนั้นกับNSCalendarUnits) NSDateComponentsไม่มีข้อมูลอ้างอิงในตัวมันเป็นเพียงโครงสร้างอย่างง่ายที่เก็บหมายเลขไว้ให้คุณเข้าถึง หากคุณต้องการได้รับยุคเช่นจากNSDateComponentsคุณจะต้องป้อนวิธีการสร้างจากNSCalendarกับNSCalendarUnitEraธง


3
การแก้ไขสิ่งนี้บรรทัดแรกควรมี NSDayCalendarUnit แทนที่จะเป็น NSWeekCalendarUnit
whitehawk

@Erik คุณใช้ปฏิทินใดอยู่ รหัส?
Itai Ferber

7
@Jonny ผลลัพธ์ที่คุณได้รับขึ้นอยู่กับปฏิทินที่คุณใช้ NSCalendar's +currentCalendarวิธีการจะกลับปฏิทินระบบและดังนั้นหากโทรศัพท์ของผู้ใช้ถูกตั้งค่าเป็นโหมดเวลาญี่ปุ่นหรือไทย, คุณจะได้รับในปีที่แตกต่างกัน หากคุณต้องการบังคับให้ระบบปฏิทินที่เฉพาะเจาะจงสร้างปฏิทินและเริ่มต้นด้วยสถานที่ที่เหมาะสม ตัวอย่างเช่นในการบังคับใช้ปฏิทินแบบคริสต์ศักราชคุณจะต้องใช้สิ่งต่อไปนี้:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
Itai Ferber

2
enums NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit ถูกเลิกใช้ใช้ NSCalendarUnitDay แทน
Kunal Balani

2
คำเตือน: อย่าใช้ [NSCalendar currentCalendar] นอกจากว่าคุณกำลังพยายามแสดงค่าให้กับผู้ใช้ พิจารณาว่าผู้ใช้อาจติดตามปฏิทินทางพุทธศาสนา (ปีนี้คือปี 2558 หรืออะไรทำนองนั้น) หรือปฏิทินแปลก ๆ จำนวนอื่น คุณไม่ต้องการให้แอปของคุณพังในกรณีเหล่านี้ ใช้ปฏิทินเกรโกเรียนเว้นแต่คุณจะมีเหตุผลที่เฉพาะเจาะจงไม่ให้ทำ ข้อผิดพลาดนี้จับยากเพราะคุณและผู้ทดสอบของคุณอาจใช้เกรกอเรียนเป็นค่าเริ่มต้น
n13

51

คุณสามารถแยกส่วนประกอบของ NSDate โดยใช้ 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]];

หากคุณต้องการรับหมายเลขเดือนแทนที่จะเป็นตัวย่อให้ใช้ "MM" หากคุณต้องการรับจำนวนเต็มใช้[myDayString intValue];


1
ขยายความเมื่อเขาด้วยส่วนสำคัญนี้ ขอให้สนุก --- คุณสามารถวางมันลงในโค้ดของคุณได้
DogEatDog

แก้ปัญหาการใช้วันที่เพื่อค้นหาในพจนานุกรม :) ขอบคุณ!
mlunoe

1
สิ่งนี้ใช้งานไม่ได้จริง 100% ตามที่คาดไว้ตลอดเวลา ตัวอย่างเช่นหาก NSDate คือ 2013-12-31 00:00:00 +0000 วันที่จัดรูปแบบจะส่งคืน 2014 สำหรับปีแม้ว่าจำนวนจริงในวันที่คือ 2013
margusholland

ฉันจะได้รับวันของปีเช่น 10 เมษายนเป็นวันปัจจุบันเป็นวันที่ 99 ของปีปัจจุบัน? -
พัฒนา iOS

17

เพียงแค่ใส่รหัสใหม่ของ Itai (และใช้งานได้!) นี่คือตัวอย่างคลาสผู้ช่วยที่จะส่งคืนค่าปีของตัวแปร NSDate ที่กำหนด

อย่างที่คุณเห็นมันง่ายพอที่จะแก้ไขรหัสนี้เพื่อรับเดือนหรือวัน

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

(ฉันไม่อยากจะเชื่อเลยว่าเราจะต้องเขียนฟังก์ชั่นพื้นฐานวันที่ของ iOS ของเราเองในปี 2013

อีกอย่างหนึ่ง: อย่าใช้ <และ> เพื่อเปรียบเทียบสองค่า NSDate

XCode จะยอมรับรหัสดังกล่าวอย่างมีความสุข (โดยไม่มีข้อผิดพลาดหรือคำเตือน) แต่ผลลัพธ์ของลอตเตอรีนั้นเป็นลอตเตอรี คุณต้องใช้ฟังก์ชั่น "เปรียบเทียบ" เพื่อเปรียบเทียบ NSDates:

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

4
ผลลัพธ์ของการเปรียบเทียบตัวชี้นั้นอยู่ไกลจากลอตเตอรีซึ่งเป็นผลลัพธ์ที่กำหนดไว้อย่างดีตราบใดที่คุณใช้สิ่งที่พวกเขาตั้งใจจะเปรียบเทียบตัวชี้ไม่ใช่วัตถุ
Richard J. Ross III

อาจไม่ใช่ลอตเตอรี่ แต่ DateTime ของ C # นั้นใช้งานง่ายกว่ามาก ใน iOS ผู้ประกอบการที่น้อยกว่าควรเปรียบเทียบ NSDates สองตัว ... ใครจะต้องการเปรียบเทียบตัวชี้ของตัวแปร NSDate สองตัว อย่างน้อยที่สุดรายการ XCode จะแสดงคำเตือนเพื่อถามว่านี่เป็นความหมายของผู้ใช้จริงหรือไม่
Mike Gledhill

1
นั่นเป็นเพียงสัญลักษณ์ของ coder ขี้เกียจที่ไม่เข้าใจพื้นฐานของภาษาที่เขาเขียนมาและมีหลายสถานการณ์สำหรับฉันที่การเปรียบเทียบตัวชี้มีความจำเป็นสำหรับวัตถุ ObjC - โดยเฉพาะอย่างยิ่งถ้าคุณสร้างคอนเทนเนอร์แบบกำหนดเอง (แม้ว่า สิ่งต่าง ๆ ได้รับการแปลกด้วย ARC)
Richard J. Ross III

1
ฉันต้องเป็นคนขี้เกียจที่ไม่เข้าใจพื้นฐาน แต่เป็นเคล็ดลับที่ยอดเยี่ยมสำหรับไมค์!
Pier-Luc Gendreau

4
การเปรียบเทียบตัวชี้อาจจำเป็น แต่เป็นกรณีที่ใช้กันน้อยกว่ามากเมื่อเปรียบเทียบสองวัน 99.99% ของเวลาโปรแกรมเมอร์ที่สนใจในการเปรียบเทียบวันที่มากกว่าพอยน์เตอร์ พื้นฐาน C # และ. NET Framework ได้รับการออกแบบมาเพื่อทำให้สถานการณ์ที่พบบ่อยที่สุดง่ายขึ้นซึ่งทำให้โปรแกรมเมอร์มีประสิทธิผลมากขึ้นและในหลาย ๆ กรณีวัตถุประสงค์ -c รู้สึกว่ามันทำให้สิ่งต่าง ๆ โดยเจตนาลำบากยิ่งขึ้น หากคุณมีเวลาอ่านหนังสือ 800 หน้าบนพื้นฐานของภาษาทุก ๆ เสียงไชโย แต่ส่วนที่เหลือของเรามีแอพที่จะส่งมอบตรงเวลาและตามงบประมาณ
Crake

16

ใน 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

ฉันกำลังเขียนคำตอบนี้เพราะเป็นวิธีเดียวที่ไม่ให้ทางเลือกแก่คุณกลับจากNSDateComponentตัวแปรและ / หรือบังคับให้แกะตัวแปรเหล่านั้นออก (เช่นสำหรับ Swift 3)

สวิฟท์ 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)

สวิฟท์ 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 เวอร์ชั่นสนุก ๆ

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)

ฉันจะได้รับวันของปีเช่น 10 เมษายนเป็นวันปัจจุบันเป็นวันที่ 99 ของปีปัจจุบัน? -
พัฒนา iOS

และตรวจสอบให้แน่ใจว่าคุณใช้ปฏิทินแบบคริสต์ศักราชเช่นองค์ประกอบปีสำหรับปฏิทินญี่ปุ่นจะส่งกลับ 1 หลัก ..
Flovettee

8

ใหม่ใน iOS 8

ObjC

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

รวดเร็ว

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
! ที่น่าตื่นตาตื่นใจ @Yuchen Zhong
Lito

1
ยอดเยี่ยม! ทางที่ดีกว่าไวยากรณ์!
joan

4

หากคุณกำหนดเป้าหมายเป็น iOS 8 ขึ้นไปคุณสามารถใช้NSCalendarวิธีการอำนวยความสะดวกแบบใหม่เพื่อให้ได้สิ่งนี้ในรูปแบบที่กระชับยิ่งขึ้น

ขั้นแรกให้สร้างNSCalendarและใช้สิ่งที่NSDateจำเป็น

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

คุณสามารถแยกส่วนประกอบแต่ละรายการผ่าน component:fromDate:

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

หรือยิ่งกระชับยิ่งขึ้นให้ใช้NSIntegerตัวชี้ผ่านgetEra:year:month:day:fromDate:

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

สำหรับข้อมูลเพิ่มเติมและตัวอย่างตรวจสอบNSDate จัดการ Made Easy ใน iOS 8 ข้อจำกัดความรับผิดชอบฉันเขียนโพสต์


ฉันจะได้รับวันของปีเช่น 10 เมษายนเป็นวันปัจจุบันเป็นวันที่ 99 ของปีปัจจุบัน? -
พัฒนา iOS

4

ตั้งแต่ iOS 8.0 (และ OS X 10) คุณสามารถใช้วิธีส่วนประกอบเพื่อทำให้ส่วนประกอบวันที่ง่ายขึ้นเช่น:

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

ควรทำให้สิ่งต่าง ๆ ง่ายขึ้นและหวังว่าสิ่งนี้จะถูกนำไปใช้อย่างมีประสิทธิภาพ



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

ชัดเจนมากไม่ได้ให้ปีเดือนหรือวันเป็นจำนวนเต็มซึ่งเป็นสิ่งที่ฉันขอใน OP -1
Richard J. Ross III

1
Richard J. Ross III: ฉันเพิ่งแก้ไขแล้วฉันขอโทษเพราะคำตอบของฉันหายไปคำถามของคุณ
Linh Nguyen

2

นี่คือทางออกใน 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

ลองสิ่งนี้ . .

ข้อมูลโค้ด:

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

มันให้ปีปัจจุบันเดือนวันที่


1

ลองทำสิ่งต่อไปนี้:

    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

สวิฟท์ 2.x

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

คุณสามารถใช้มันเป็น

NSDate().currentDateInDayMonthYear()

เอาท์พุต

6 March 2016

1

รวดเร็ว

วิธีที่ง่ายกว่าในการรับองค์ประกอบใด ๆ ของวันที่เป็นสตริงเสริม

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

ฉันทำแบบนี้ ....

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

ในการรับสตริงที่มนุษย์สามารถอ่านได้ (วัน, เดือน, ปี) คุณสามารถทำได้:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *string = [dateFormatter stringFromDate:dateEndDate];
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.