這幾天做的東西涉及到日歷類和時(shí)間類,各種操作。代碼擼的要死。
這邊注意下,在代碼中擼的時(shí)間,系統(tǒng)默認(rèn)都是格林時(shí)間 為基準(zhǔn)的
1獲取當(dāng)前時(shí)區(qū)時(shí)間
1.1獲取當(dāng)前時(shí)間類型為NSDate類型的
獲取當(dāng)前時(shí)區(qū)
判斷當(dāng)前時(shí)區(qū)與格林時(shí)區(qū)的時(shí)間差
獲取當(dāng)前時(shí)間加上時(shí)間差
//獲取當(dāng)前時(shí)區(qū)時(shí)間
+(NSDate *)getCurrentLocaleDate:(NSDate *)ADate {
NSTimeZone *timeZone = [NSTimeZone systemTimeZone];
NSTimeInterval interval = [timeZone secondsFromGMTForDate:ADate];
NSDate *nowDate = [ADate dateByAddingTimeInterval:interval];
return nowDate;
}
1.1獲取當(dāng)前時(shí)間類型為NSString類型的
系統(tǒng)提供了了一個(gè)NSDateFormatter 類
這個(gè)format的格式是
這個(gè)太TM重要了,我以前以為
大小寫不區(qū)分的。蠢得要死,改了好長(zhǎng)時(shí)間的BUG
大家一定要記住,不能亂寫啊。亂寫的話,轉(zhuǎn)換就會(huì)出現(xiàn)問(wèn)題。
G: 公元時(shí)代,例如AD公元
yy: 年的后2位
yyyy: 完整年
MM: 月,顯示為1-12
MMM: 月,顯示為英文月份簡(jiǎn)寫,如 Jan
MMMM: 月,顯示為英文月份全稱,如 Janualy
dd: 日,2位數(shù)表示,如02
d: 日,1-2位顯示,如 2
EEE: 簡(jiǎn)寫星期幾,如Sun
EEEE: 全寫星期幾,如Sunday
aa: 上下午,AM/PM
H: 時(shí),24小時(shí)制,0-23
K:時(shí),12小時(shí)制,0-11
m: 分,1-2位
mm: 分,2位
s: 秒,1-2位
ss: 秒,2位
S: 毫秒
//獲取當(dāng)前是時(shí)間 string
+(NSString *) getCurrentLocaleString:(NSDate *) Adate {
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
outputFormatter.locale = [NSLocale currentLocale];
[outputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
return [outputFormatter stringFromDate:Adate];
}
2.從服務(wù)器獲取的時(shí)間 轉(zhuǎn)換
我當(dāng)時(shí)在從服務(wù)器獲取時(shí)間之后,就用NSDateFormatter 格式化直接用了,結(jié)果感覺(jué)蹦蹦噠0.0
我們從服務(wù)器獲取的時(shí)間都是我們當(dāng)前時(shí)區(qū)的時(shí)間,可因?yàn)楂@取的類型不通,我們需要轉(zhuǎn)換成不同的類型供我們使用, 上面的代碼 思路都是 格式時(shí)間+時(shí)間差
因?yàn)橄到y(tǒng)是按照格林時(shí)間為基準(zhǔn)的,你從服務(wù)器獲取的時(shí)間 系統(tǒng)會(huì)認(rèn)為是格林時(shí)間。 這時(shí)候你轉(zhuǎn)換的時(shí)候,就要告訴系統(tǒng),這是正確的時(shí)間 和格林時(shí)間差為0。
+(NSString *) stringFormDate:(NSDate *) Adate{
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[outputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
return [outputFormatter stringFromDate:Adate];
}
3 Date 的某一個(gè)元素 進(jìn)行調(diào)整
項(xiàng)目中一開(kāi)始有個(gè)需求就是對(duì)對(duì)明天后天 的這個(gè)時(shí)候做一些事情,我一開(kāi)始想到就是就是加上時(shí)間差。最后感覺(jué)好蠢的感覺(jué)。查了一些資料,知道系統(tǒng)的提供的日歷類,可以實(shí)現(xiàn)這些操作。
正書就是+ 負(fù)數(shù)就是?
+(NSDate *)addYear:(NSInteger)year Month:(NSInteger)month Day:(NSInteger)day date:(NSDate *)date{
//這個(gè)是日歷類
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
//date元素類,可以對(duì)date的元素操作。
NSDateComponents *adcomps = [[NSDateComponents alloc] init];
[adcomps setYear:year];
[adcomps setMonth:month];
[adcomps setDay:day];
NSDate *date1 = [calendar dateByAddingComponents:adcomps toDate:date options:0];
return date1;
}
我這邊只寫了年月日 不過(guò)NSDateCompoents 提供了這么多屬性。想怎么玩就怎么玩。
@property NSInteger era;
@property NSInteger year;
@property NSInteger month;
@property NSInteger day;
@property NSInteger hour;
@property NSInteger minute;
@property NSInteger second;
@property NSInteger nanosecond NS_AVAILABLE(10_7, 5_0);
@property NSInteger weekday;
@property NSInteger weekdayOrdinal;
@property NSInteger quarter NS_AVAILABLE(10_6, 4_0);
@property NSInteger weekOfMonth NS_AVAILABLE(10_7, 5_0);
@property NSInteger weekOfYear NS_AVAILABLE(10_7, 5_0);
@property NSInteger yearForWeekOfYear NS_AVAILABLE(10_7, 5_0);
4 Date 倒計(jì)時(shí)功能
項(xiàng)目中還需要實(shí)現(xiàn)倒計(jì)時(shí)功能,我第一個(gè)想到的就是全部換成 秒 進(jìn)行運(yùn)算(感覺(jué)自己蠢得要死)。
其實(shí) 實(shí)現(xiàn)倒計(jì)時(shí)功能挺簡(jiǎn)單的,但其中還挺多坑的。
我簡(jiǎn)單提一下,要實(shí)現(xiàn)倒計(jì)時(shí)2種方法。
一個(gè)用NSTimer(這個(gè)要涉及到NSRunLoop )
一個(gè)用GCD(這個(gè)寫起來(lái)煩的要死,不過(guò)性能據(jù)說(shuō)是杠杠的)
我代碼都貼出來(lái)一下吧
4.1 NSTimer
//設(shè)置一個(gè)未來(lái)的時(shí)間 計(jì)算時(shí)間差
- (void)resetTimerWithDate:(NSDate *)futureDate{
NSTimeInterval futureTimeInterval = [futureDate timeIntervalSinceDate:[[NSDate date] dateByAddingTimeInterval:3600*8]];
self.interval = futureTimeInterval;
if (self.timer == nil) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeDecrease:) userInfo:nil repeats:YES];
//因?yàn)槲襱imer 是放在UI線程的 要指定NSRunloop的模式為NSRunLoopCommonModes
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
}
- (void)timeDecrease:(NSTimer *)timer{
self.interval --;
if (self.interval <= 0) {
//如果計(jì)數(shù)器 = 0 或者 自己已經(jīng)不在屏幕上了
[timer invalidate];
timer = nil;
return;
}
int day = self.interval/(3600*24);
int hour = (self.interval - day*(3600*24))/3600.0;
int min = (self.interval - day*(3600*24) - hour*3600)/60;
int sec = (self.interval - day*(3600*24) - hour*3600 - min*60);
NSArray *arr = @[@(day),@(hour),@(min),@(sec)];
//到這里已經(jīng)可以獲取到具體的時(shí)差 這邊可以顯示在你
}
如果timer放在子線程里面, 可以不用設(shè)置Runloop的模式,但有一個(gè)要注意要手動(dòng)啟動(dòng)runloop
4.2GCD
//這個(gè)_timer 設(shè)置成成員變量
{
dispatch_source_t _timer;
}
//借用上面的計(jì)算時(shí)間間隔的方法 計(jì)算出時(shí)間間隔
__block int timeout = timeInterval; //倒計(jì)時(shí)時(shí)間
//創(chuàng)建一個(gè)專門執(zhí)行timer回調(diào)的GCD隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("my queue", 0);
//創(chuàng)建Timer
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//使用dispatch_source_set_timer函數(shù)設(shè)置timer參數(shù)
dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), interval, 0);
//設(shè)置回調(diào)
dispatch_source_set_event_handler(_timer, ^(){
if(timeout<=0)
{ //倒計(jì)時(shí)結(jié)束,關(guān)閉
dispatch_source_cancel(_timer);
_timer = nil;
dispatch_async(dispatch_get_main_queue(), ^{
//主線程顯示
});
timeout--;
});
//dispatch_source默認(rèn)是Suspended狀態(tài),通過(guò)dispatch_resume函數(shù)開(kāi)始它
dispatch_resume(_timer);
關(guān)于rounloop和timer 可以看這邊https://www.mgenware.com/blog/?p=459