ある特定の日まで,あと何日残されているか?を計算しようとしたところ,タイムゾーンとか,今日を取得すると時刻もついてきてしまうので,「感覚的に」違和感が出るとのご指摘.
ということで「特定の日」が”yyyy-MM-dd”(2023-08-20形式)で与えられた場合の残り日数の計算結果の違和感の解消を目指します.
- 「特定の日」には,時刻もなければタイムゾーンも無い.漠然と「今いるタイムゾーンの,その日,しかもNSStringで渡す.」という解釈・条件である.
- 「今」を取得した時,タイムゾーンがGMT(標準時)のものが返って来た.「特定の日」が日本時間で設定されていると9時間の差がある.
- なので15時を境に1日増えたり減ったりする結果になっていたため違和感があった.
- 「特定の日」も「今」も,日付だけを抽出しよう
- どちらも時刻成分は取り除いてGMTで扱おう
- たぶん日本時間で”00:00:00″はGMTだと”前日の15:00:00″になるけど「残り何日」を計算するので時差のことは気にしなくてよくなる
/// Get remaining days from today to specified date without considerting time components
/// @param expilation date in "yyyy-MM-dd" format(without time components)
/// @return remaining days
- (int) getRemainingDays:(NSString *)expilationDate
{
// Get NSDate of "yyyy/MM/dd" format
NSDateFormatter *formatter = [[NSDateFormatter alloc] initWithDateFormat:@"%Y/%m/%d" allowNaturalLanguage:YES];
// Get today and extract year/month/day only with format "yyyy-MM-dd"
NSCalendar *cal = [NSCalendar currentCalendar];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *comp = [cal components:unitFlags fromDate:[NSDate date]];
NSString *todayDate = [[NSString alloc] initWithFormat:@"%04ld-%02ld-%02ld", (long)comp.year, comp.month, comp.day];
// Get NSDates without time components
NSDate *today = [formatter dateFromString:todayDate];
NSDate *target = [formatter dateFromString:expilationDate];
// Get the STARTING TIME of specified date (e.g. "2022-07-31 00:00:00" for "2022-07-31 12:34:56")
NSDate *fromDate;
NSDate *toDate;
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar rangeOfUnit:NSCalendarUnitDay startDate:&fromDate interval:NULL forDate:today];
[calendar rangeOfUnit:NSCalendarUnitDay startDate:&toDate interval:NULL forDate:target];
// Calculate differene in days
NSDateComponents *difference
= [calendar components:NSCalendarUnitDay
fromDate:fromDate
toDate:toDate
options:0];
return (int)[difference day];
}