ChartsDemo-iOS/Objective-C/Formatters/DayAxisValueFormatter.m (132 lines of code) (raw):
//
// DayAxisValueFormatter.m
// ChartsDemo
// Copyright © 2016 dcg. All rights reserved.
//
#import "DayAxisValueFormatter.h"
@implementation DayAxisValueFormatter
{
NSArray *months;
__weak BarLineChartViewBase *_chart;
}
- (id)initForChart:(BarLineChartViewBase *)chart
{
self = [super init];
if (self)
{
self->_chart = chart;
months = @[
@"Jan", @"Feb", @"Mar",
@"Apr", @"May", @"Jun",
@"Jul", @"Aug", @"Sep",
@"Oct", @"Nov", @"Dec"
];
}
return self;
}
- (NSString *)stringForValue:(double)value
axis:(ChartAxisBase *)axis
{
int days = (int)value;
int year = [self determineYearForDays:days];
int month = [self determineMonthForDayOfYear:days];
NSString *monthName = months[month % months.count];
NSString *yearName = [@(year) stringValue];
if (_chart.visibleXRange > 30 * 6)
{
return [NSString stringWithFormat:@"%@ %@", monthName, yearName];
}
else
{
int dayOfMonth = [self determineDayOfMonthForDays:days month:month + 12 * (year - 2016)];
NSString *appendix = @"th";
switch (dayOfMonth)
{
case 1:
appendix = @"st";
break;
case 2:
appendix = @"nd";
break;
case 3:
appendix = @"rd";
break;
case 21:
appendix = @"st";
break;
case 22:
appendix = @"nd";
break;
case 23:
appendix = @"rd";
break;
case 31:
appendix = @"st";
break;
}
return dayOfMonth == 0 ? @"" : [NSString stringWithFormat:@"%d%@ %@", dayOfMonth, appendix, monthName];
}
}
- (int)daysForMonth:(int)month year:(int)year
{
// month is 0-based
if (month == 1)
{
BOOL is29Feb = NO;
if (year < 1582)
{
is29Feb = (year < 1 ? year + 1 : year) % 4 == 0;
}
else if (year > 1582)
{
is29Feb = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
return is29Feb ? 29 : 28;
}
if (month == 3 || month == 5 || month == 8 || month == 10)
{
return 30;
}
return 31;
}
- (int)determineMonthForDayOfYear:(int)dayOfYear
{
int month = -1;
int days = 0;
while (days < dayOfYear)
{
month = month + 1;
if (month >= 12)
month = 0;
int year = [self determineYearForDays:days];
days += [self daysForMonth:month year:year];
}
return MAX(month, 0);
}
- (int)determineDayOfMonthForDays:(int)days month:(int)month
{
int count = 0;
int daysForMonths = 0;
while (count < month)
{
int year = [self determineYearForDays:days];
daysForMonths += [self daysForMonth:count % 12 year:year];
count++;
}
return days - daysForMonths;
}
- (int)determineYearForDays:(int)days
{
if (days <= 366)
{
return 2016;
}
else if (days <= 730)
{
return 2017;
}
else if (days <= 1094)
{
return 2018;
}
else if (days <= 1458)
{
return 2019;
}
return 2020;
}
@end