天天看點

iphone——日期處理Dates NSCalendar & NSDateComponents 曆法計算

轉自:

http://blog.csdn.net/lingedeng/article/details/6996599

        nsdate類提供了建立date,比較date以及計算兩個date之間間隔的功能。date對象是不可改變的。

        如果你要建立date對象并表示目前日期,你可以alloc一個nsdate對象并調用init初始化:

[cpp] view

plaincopy

nsdate *now = [[nsdate alloc] init];  

        或者使用nsdate的date類方法來建立一個日期對象。如果你需要與目前日期不同的日期,你可以使用nsdate的initwithtimeinterval...或datewithtimeinterval...方法,你也可以使用更複雜的calendar或date

components對象。

        建立一定時間間隔的nsdate對象:

[plain] view

nstimeinterval secondsperday = 24 * 60 * 60;  

nsdate *tomorrow = [[nsdate alloc] initwithtimeintervalsincenow:secondsperday];  

nsdate *yesterday = [[nsdate alloc] initwithtimeintervalsincenow:-secondsperday];  

[tomorrow release];  

[yesterday release];  

        使用增加時間間隔的方式來生成nsdate對象:

nsdate *today = [[nsdate alloc] init];  

nsdate *tomorrow, *yesterday;  

tomorrow = [today datebyaddingtimeinterval: secondsperday];  

yesterday = [today datebyaddingtimeinterval: -secondsperday];  

[today release];  

        如果要對nsdate對象進行比較,可以使用isequaltodate:, compare:, laterdate:和 earlierdate:方法。這些方法都進行精确比較,也就是說這些方法會一直精确比較到nsdate對象中秒一級。例如,你可能比較兩個日期,如果他們之間的間隔在一分鐘之内則認為這兩個日期是相等的。在這種情況下使用,timeintervalsincedate:方法來對兩個日期進行比較。下面的代碼進行了示例:

if (fabs([date2 timeintervalsincedate:date1]) < 60) ...  

        月曆對象封裝了對系統日期的計算,包括這一年開始,總天數以及劃分。你将使用月曆對象對絕對日期與date components(包括年,月,日,時,分,秒)進行轉換。

        nscalendar定義了不同的月曆,包括佛教曆,格裡高利曆等(這些都與系統提供的本地化設定相關)。nscalendar與nsdatecomponents對象緊密相關。

        你可以通過nscalendar對象的currentcalendar方法來獲得目前系統使用者設定的月曆。

nscalendar *currentcalendar = [nscalendar currentcalendar];  

nscalendar *japanesecalendar = [[nscalendar alloc] initwithcalendaridentifier:nsjapanesecalendar];  

nscalendar *userscalendar = [[nslocale currentlocale] objectforkey:nslocalecalendar];  

        userscalendar和currentcalendar對象是相等的,盡管他們是不同的對象。

        你可以使用nsdatecomponents對象來表示一個日期對象的元件——例如年,月,日和小時。如果要使一個nsdatecomponents對象有意義,你必須将其與一個月曆對象相關聯。下面的代碼示例了如何建立一個nsdatecomponents對象:

nsdatecomponents *components = [[nsdatecomponents alloc] init];  

[components setday:6];  

[components setmonth:5];  

[components setyear:2004];  

nsinteger weekday = [components weekday]; // undefined (== nsundefineddatecomponent)  

        要将一個日期對象解析到相應的date components,你可以使用nscalendar的components:fromdate:方法。此外日期本身,你需要指定nsdatecomponents對象傳回元件。

nsdate *today = [nsdate date];  

nscalendar *gregorian = [[nscalendar alloc] initwithcalendaridentifier:nsgregoriancalendar];  

nsdatecomponents *weekdaycomponents = [gregorian components:(nsdaycalendarunit | nsweekdaycalendarunit) fromdate:today];  

nsinteger day = [weekdaycomponents day];  

nsinteger weekday = [weekdaycomponents weekday];  

同樣你也可以從nsdatecomponents對象來建立nsdate對象:  

[components setweekday:2]; // monday  

[components setweekdayordinal:1]; // the first monday in the month  

[components setmonth:5]; // may  

[components setyear:2008];  

nsdate *date = [gregorian datefromcomponents:components];  

        為了保證正确的行為,您必須確定使用的元件在月曆上是有意義的。指定“出界”月曆元件,如一個-6或2月30日在公曆中的日期值産生未定義的行為。

        你也可以建立一個不帶年份的nsdate對象,這樣的作業系統會自動生成一個年份,但在後面的代碼中不會使用其自動生成的年份。

[components setmonth:11];  

[components setday:7];  

nsdate *birthday = [gregorian datefromcomponents:components];  

        下面的示例顯示了如何從一個月曆置換到另一個月曆:

nsdatecomponents *comps = [[nsdatecomponents alloc] init];  

[comps setday:6];  

[comps setmonth:5];  

[comps setyear:2004];  

nsdate *date = [gregorian datefromcomponents:comps];  

[comps release];  

[gregorian release];  

nscalendar *hebrew = [[nscalendar alloc] initwithcalendaridentifier:nshebrewcalendar];  

nsuinteger unitflags = nsdaycalendarunit | nsmonthcalendarunit | nsyearcalendarunit;  

nsdatecomponents *components = [hebrew components:unitflags fromdate:date];  

nsinteger day = [components day]; // 15  

nsinteger month = [components month]; // 9  

nsinteger year = [components year]; // 5764  

        在目前時間加上一個半小時:

nsdatecomponents *offsetcomponents = [[nsdatecomponents alloc] init];  

[offsetcomponents sethour:1];  

[offsetcomponents setminute:30];  

// calculate when, according to tom lehrer, world war iii will end  

nsdate *endofworldwar3 = [gregorian datebyaddingcomponents:offsetcomponents todate:today options:0];  

        獲得目前星期中的星期天(使用格裡高利曆):

// get the weekday component of the current date  

nsdatecomponents *weekdaycomponents = [gregorian components:nsweekdaycalendarunit fromdate:today];  

/*  

create a date components to represent the number of days to subtract from the current date.  

the weekday value for sunday in the gregorian calendar is 1, so subtract 1 from the number of days to subtract from the date in question.  (if today is sunday, subtract 0 days.)  

*/  

nsdatecomponents *componentstosubtract = [[nsdatecomponents alloc] init];  

[componentstosubtract setday: 0 - ([weekdaycomponents weekday] - 1)];  

nsdate *beginningofweek = [gregorian datebyaddingcomponents:componentstosubtract todate:today options:0];  

optional step:  

beginningofweek now has the same hour, minute, and second as the original date (today).  

to normalize to midnight, extract the year, month, and day components and create a new date from those components.  

nsdatecomponents *components = [gregorian components:(nsyearcalendarunit | nsmonthcalendarunit | nsdaycalendarunit) fromdate: beginningofweek];  

beginningofweek = [gregorian datefromcomponents:components];  

        如何可以計算出一周的第一天(根據系統的月曆設定):

nsdate *beginningofweek = nil;  

bool ok = [gregorian rangeofunit:nsweekcalendarunit startdate:&beginningofweek interval:null fordate: today];  

        獲得兩個日期之間的間隔:

nsdate *startdate = ...;  

nsdate *enddate = ...;  

nsuinteger unitflags = nsmonthcalendarunit | nsdaycalendarunit;  

nsdatecomponents *components = [gregorian components:unitflags fromdate:startdate todate:enddate options:0];  

nsinteger months = [components month];  

nsinteger days = [components day];  

        使用category來計算同一時代(ad|bc)兩個日期午夜之間的天數:

@implementation nscalendar (myspecialcalculations)  

-(nsinteger)dayswithinerafromdate:(nsdate *) startdate todate:(nsdate *) enddate {  

     nsinteger startday=[self ordinalityofunit:nsdaycalendarunit inunit: nseracalendarunit fordate:startdate];  

     nsinteger endday=[self ordinalityofunit:nsdaycalendarunit inunit: nseracalendarunit fordate:enddate];  

     return endday-startday;  

}  

@end  

        使用category來計算不同時代(ad|bc)兩個日期的天數:

@implementation nscalendar (myothermethod)  

-(nsinteger) daysfromdate:(nsdate *) startdate todate:(nsdate *) enddate {  

     nscalendarunit units=nseracalendarunit | nsyearcalendarunit | nsmonthcalendarunit | nsdaycalendarunit;  

     nsdatecomponents *comp1=[self components:units fromdate:startdate];  

     nsdatecomponents *comp2=[self components:units fromdate enddate];  

     [comp1 sethour:12];  

     [comp2 sethour:12];  

     nsdate *date1=[self datefromcomponents: comp1];  

     nsdate *date2=[self datefromcomponents: comp2];  

     return [[self components:nsdaycalendarunit fromdate:date1 todate:date2 options:0] day];  

        判斷一個日期是否在目前一周内(使用格裡高利曆):

-(bool)isdatethisweek:(nsdate *)date {  

     nsdate *start;  

     nstimeinterval extends;  

     nscalendar *cal=[nscalendar autoupdatingcurrentcalendar];  

     nsdate *today=[nsdate date];  

     bool success= [cal rangeofunit:nsweekcalendarunit startdate:&start interval: &extends fordate:today];  

     if(!success)  

        return no;  

     nstimeinterval dateinsecs = [date timeintervalsincereferencedate];  

     nstimeinterval daystartinsecs= [start timeintervalsincereferencedate];  

     if(dateinsecs > daystartinsecs && dateinsecs < (daystartinsecs+extends)){  

          return yes;  

     }  

     else {  

          return no;  

}  

方法2:

+(nsstring*)getydealdatetostring:(int)day{

    nsdate *curdate = [nsdate date];

    nscalendar* calendar = [nscalendar currentcalendar];

    nsdatecomponents* comps = [calendar components:nsyearcalendarunit|nsmonthcalendarunit|nsweekcalendarunit|nsweekdaycalendarunit fromdate:curdate];

    comps = [calendar components:nsyearcalendarunit|nsmonthcalendarunit|nsweekcalendarunit|nsweekdaycalendarunit fromdate:curdate]; 

    [comps setmonth:[comps month]+1];

    [comps setday:day];

    nsdate *tdatemonth = [calendar datefromcomponents:comps];

    nsstring *datestr=[nsstring stringwithformat:@"%@",tdatemonth];

    return datestr;

}

參數:day天數,可以是負數

用法:

nslog(@"%@",[你的類名 getydealdatetostring:-30]);

如果今天的日期是2013-03-31 21:56:23

則輸出:2013-02-28 21:56:23