Skip to content

Instantly share code, notes, and snippets.

@mattt
Created December 26, 2014 17:09
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save mattt/7edb54f8f4fde4a3783e to your computer and use it in GitHub Desktop.
Save mattt/7edb54f8f4fde4a3783e to your computer and use it in GitHub Desktop.
protocol Calendar {
typealias Unit: BidirectionalIndexType
typealias Era: Unit
typealias Year: Unit
typealias Month: Unit
typealias Week: Unit
typealias Day: Unit
typealias Weekday: Unit
typealias Hour: Unit
typealias Minute: Unit
typealias Second: Unit
class func era(date: Date<Self>) -> Era
class func year(date: Date<Self>) -> Year
class func isLeapYear(date: Date<Self>) -> Bool
class func weekOfYear(date: Date<Self>) -> Week
class func dayOfYear(date: Date<Self>) -> Day
class func month(date: Date<Self>) -> Month
class func weekOfMonth(date: Date<Self>) -> Week
class func dayOfMonth(date: Date<Self>) -> Day
class func dayOfWeek(date: Date<Self>) -> Weekday
class func hour(date: Date<Self>) -> Hour
class func minute(date: Date<Self>) -> Minute
class func second(date: Date<Self>) -> Second
}
// http://en.wikipedia.org/wiki/Gregorian_calendar
struct GregorianCalendar: Calendar {
enum Era {
case BCE, AD
}
typealias Year = Int
enum Month {
case January, February, March, April, May, June, July, August, September, October, November, December
}
enum Weekday {
case Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
}
// ...
}
// http://en.wikipedia.org/wiki/French_Republican_Calendar
struct FrenchRepublicanCalendar: Calendar {
enum Era {
case Republican
}
typealias Year = Int
enum Month {
// Autumn
case Vendémiaire // (from Latin vindemia, "grape harvest"), starting 22, 23 or 24 September
case Brumaire // (from French brume, "fog"), starting 22, 23 or 24 October
case Frimaire // (from French frimas, "frost"), starting 21, 22 or 23 November
// Winter
case Nivôse // (from Latin nivosus, "snowy"), starting 21, 22 or 23 December
case Pluviôse // (from Latin pluvius, "rainy"), starting 20, 21 or 22 January
case Ventôse // (from Latin ventosus, "windy"), starting 19, 20 or 21 February
// Spring
case Germinal // (from Latin germen, "germination"), starting 20 or 21 March
case Floréal // (from Latin flos, "flower"), starting 20 or 21 April
case Prairial // (from French prairie, "pasture"), starting 20 or 21 May
// Summer
case Messidor // (from Latin messis, "harvest"), starting 19 or 20 June
case Thermidor // (from Greek thermon, "summer heat"), starting 19 or 20 July
case Fructidor // (from Latin fructus, "fruit"), starting 18 or 19 August
}
enum Weekday {
case Primidi, Duodi, Tridi, Quartidi, Quintidi, Sextidi, Septidi, Octidi, Nonidi, Décadi
}
}
struct Date<C: Calendar>: Comparable {
typealias Calendar = C
let timestamp: Int
var era: Calendar.Era {
return Calendar.era(self)
}
var year: Calendar.Year {
return Calendar.year(self)
}
var weekOfYear: Calendar.Week {
return Calendar.weekOfYear(self)
}
var month: Calendar.Month {
return Calendar.month(self)
}
var weekOfMonth: Calendar.Week {
return Calendar.weekOfMonth(self)
}
var dayOfMonth: Calendar.Day {
return Calendar.dayOfMonth(self)
}
var dayOfWeek: Calendar.Weekday {
return Calendar.dayOfWeek(self)
}
var hour: Calendar.Hour {
return Calendar.hour(self)
}
var minute: Calendar.Minute {
return Calendar.minute(self)
}
var second: Calendar.Second {
return Calendar.second(self)
}
typealias Components = (era: Calendar.Era, year: Calendar.Year, weekOfYear: Calendar.Week, month: Calendar.Month, weekOfMonth: Calendar.Week, dayOfMonth: Calendar.Day, dayOfWeek: Calendar.Weekday, hour: Calendar.Hour, minute: Calendar.Minute, second: Calendar.Second)
var components: Components {
return (era, year, weekOfYear, month, weekOfMonth, dayOfMonth, dayOfWeek, hour, minute, second)
}
init(secondsAfterEpoch seconds: Int) {
// ...
}
init(components: Components) {
// ...
}
}
// MARK: Equatable
func ==<T: Calendar>(lhs: Date<T>, rhs: Date<T>) -> Bool {
return lhs.timestamp == rhs.timestamp
}
// MARK: Comparable
func <<T: Calendar>(lhs: Date<T>, rhs: Date<T>) -> Bool {
return lhs.timestamp < rhs.timestamp
}
// MARK: ISO 8601
extension Date {
var ISO8601Timestamp: String {
return ""
}
init?(ISO8601 timestamp: String) {
return nil
}
}
// MARK: Indexing Views
struct LazyBidirectionalCalendarView<T: CalendarUnit> {
// ...
}
extension Date {
var yearlyView: LazyBidirectionalCalendarView<Calendar.Year> {
return LazyBidirectionalCalendarView()
}
// ...
}
// MARK: Conversion
func convert<T: Calendar, U: Calendar>(date: Date<T>) -> Date<U> {
return Date<U>(secondsAfterEpoch: date.timestamp)
}
// MARK: Overloaded Operators
func +<T: Calendar>(lhs: Date<T>, rhs: Date<T>) -> Date<T> {
// ...
}
func +<T: Calendar>(lhs: Date<T>, rhs: (Int, T.Unit)) {
// ...
}
func -<T: Calendar>(lhs: Date<T>, rhs: (Int, T.Unit)) {
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment