ChartsDemo-iOS/Swift/Formatters/DayAxisValueFormatter.swift (81 lines of code) (raw):
//
// DayAxisValueFormatter.swift
// ChartsDemo-iOS
//
// Created by Jacob Christie on 2017-07-09.
// Copyright © 2017 jc. All rights reserved.
//
import Foundation
import Charts
public class DayAxisValueFormatter: NSObject, AxisValueFormatter {
weak var chart: BarLineChartViewBase?
let months = ["Jan", "Feb", "Mar",
"Apr", "May", "Jun",
"Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"]
init(chart: BarLineChartViewBase) {
self.chart = chart
}
public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
let days = Int(value)
let year = determineYear(forDays: days)
let month = determineMonth(forDayOfYear: days)
let monthName = months[month % months.count]
let yearName = "\(year)"
if let chart = chart,
chart.visibleXRange > 30 * 6 {
return monthName + yearName
} else {
let dayOfMonth = determineDayOfMonth(forDays: days, month: month + 12 * (year - 2016))
var appendix: String
switch dayOfMonth {
case 1, 21, 31: appendix = "st"
case 2, 22: appendix = "nd"
case 3, 23: appendix = "rd"
default: appendix = "th"
}
return dayOfMonth == 0 ? "" : String(format: "%d\(appendix) \(monthName)", dayOfMonth)
}
}
private func days(forMonth month: Int, year: Int) -> Int {
// month is 0-based
switch month {
case 1:
var is29Feb = false
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
case 3, 5, 8, 10:
return 30
default:
return 31
}
}
private func determineMonth(forDayOfYear dayOfYear: Int) -> Int {
var month = -1
var days = 0
while days < dayOfYear {
month += 1
if month >= 12 {
month = 0
}
let year = determineYear(forDays: days)
days += self.days(forMonth: month, year: year)
}
return max(month, 0)
}
private func determineDayOfMonth(forDays days: Int, month: Int) -> Int {
var count = 0
var daysForMonth = 0
while count < month {
let year = determineYear(forDays: days)
daysForMonth += self.days(forMonth: count % 12, year: year)
count += 1
}
return days - daysForMonth
}
private func determineYear(forDays days: Int) -> Int {
switch days {
case ...366: return 2016
case 367...730: return 2017
case 731...1094: return 2018
case 1095...1458: return 2019
default: return 2020
}
}
}