Skip to content

Commit

Permalink
Remove DateCalculator
Browse files Browse the repository at this point in the history
  • Loading branch information
iSoron committed Mar 31, 2019
1 parent 70a7985 commit aa6b13f
Show file tree
Hide file tree
Showing 23 changed files with 276 additions and 233 deletions.
13 changes: 10 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
*.iml
*.pbxuser
*.perspective
*.perspectivev3
*.swp
*~.nib
.DS_Store
.externalNativeBuild
.gradle
local.properties
.idea
.DS_Store
build
build/
captures
.externalNativeBuild
local.properties
node_modules
*xcuserdata*
12 changes: 3 additions & 9 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ buildscript {

dependencies {
classpath "com.android.tools.build:gradle:3.2.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.21"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.11"
}
}

Expand All @@ -42,17 +42,11 @@ apply plugin:"kotlin-multiplatform"

kotlin {
targets {
def iosPreset = System.getenv('SDK_NAME')?.startsWith("iphoneos") ? presets.iosArm64 : presets.iosX64
fromPreset(presets.jvm, 'jvm')

fromPreset(presets.iosX64, 'iOS') {
fromPreset(iosPreset, 'iOS') {
compilations.main.outputKinds('FRAMEWORK')
}

// Replace the target above by the following one to produce a framework
// which can be installed on a real iPhone:
// fromPreset(presets.iosArm64, 'iOS') {
// compilations.main.outputKinds('FRAMEWORK')
// }
}

sourceSets {
Expand Down
151 changes: 123 additions & 28 deletions core/src/commonMain/kotlin/org/isoron/platform/time/Dates.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,48 +31,143 @@ enum class DayOfWeek(val index: Int) {
SATURDAY(6),
}

data class Timestamp(val unixTimeInMillis: Long)
data class Timestamp(val millisSince1970: Long) {
val localDate: LocalDate
get() {
val millisSince2000 = millisSince1970 - 946684800000
val daysSince2000 = millisSince2000 / 86400000
return LocalDate(daysSince2000.toInt())
}
}

data class LocalDate(val daysSince2000: Int) {

var yearCache = -1
var monthCache = -1
var dayCache = -1

init {
if (daysSince2000 < 0)
throw IllegalArgumentException("$daysSince2000 < 0")
}

constructor(year: Int, month: Int, day: Int) :
this(daysSince2000(year, month, day))

val dayOfWeek: DayOfWeek
get() {
return when (daysSince2000 % 7) {
0 -> DayOfWeek.SATURDAY
1 -> DayOfWeek.SUNDAY
2 -> DayOfWeek.MONDAY
3 -> DayOfWeek.TUESDAY
4 -> DayOfWeek.WEDNESDAY
5 -> DayOfWeek.THURSDAY
else -> DayOfWeek.FRIDAY
}
}

val timestamp: Timestamp
get() {
return Timestamp(946684800000 + daysSince2000.toLong() * 86400000)
}

val year: Int
get() {
if (yearCache < 0) updateYearMonthDayCache()
return yearCache
}

val month: Int
get() {
if (monthCache < 0) updateYearMonthDayCache()
return monthCache
}

val day: Int
get() {
if (dayCache < 0) updateYearMonthDayCache()
return dayCache
}

private fun updateYearMonthDayCache() {
var currYear = 2000
var currDay = 0

while (true) {
val currYearLength = if (isLeapYear(currYear)) 366 else 365
if (daysSince2000 < currDay + currYearLength) {
yearCache = currYear
break
} else {
currYear++
currDay += currYearLength
}
}

var currMonth = 1
val monthOffset = if (isLeapYear(currYear)) leapOffset else nonLeapOffset

while (true) {
if (daysSince2000 < currDay + monthOffset[currMonth]) {
monthCache = currMonth
break
} else {
currMonth++
}
}

data class LocalDate(val year: Int,
val month: Int,
val day: Int) {
currDay += monthOffset[currMonth - 1]
dayCache = daysSince2000 - currDay + 1

}

fun isOlderThan(other: LocalDate): Boolean {
if (other.year != year) return other.year > year
if (other.month != month) return other.month > month
return other.day > day
return daysSince2000 < other.daysSince2000
}

fun isNewerThan(other: LocalDate): Boolean {
if (this == other) return false
return other.isOlderThan(this)
return daysSince2000 > other.daysSince2000
}

init {
if ((month <= 0) or (month >= 13)) throw(IllegalArgumentException())
if ((day <= 0) or (day >= 32)) throw(IllegalArgumentException())
fun plus(days: Int): LocalDate {
return LocalDate(daysSince2000 + days)
}
}

interface LocalDateCalculator {
fun plusDays(date: LocalDate, days: Int): LocalDate
fun dayOfWeek(date: LocalDate): DayOfWeek
fun toTimestamp(date: LocalDate): Timestamp
fun fromTimestamp(timestamp: Timestamp): LocalDate
}

fun LocalDateCalculator.distanceInDays(d1: LocalDate, d2: LocalDate): Int {
val t1 = toTimestamp(d1)
val t2 = toTimestamp(d2)
val dayLength = 24 * 60 * 60 * 1000
return abs((t2.unixTimeInMillis - t1.unixTimeInMillis) / dayLength).toInt()
}
fun minus(days: Int): LocalDate {
return LocalDate(daysSince2000 - days)
}

fun LocalDateCalculator.minusDays(date: LocalDate, days: Int): LocalDate {
return plusDays(date, -days)
fun distanceTo(other: LocalDate): Int {
return abs(daysSince2000 - other.daysSince2000)
}
}

interface LocalDateFormatter {
fun shortWeekdayName(date: LocalDate): String
fun shortMonthName(date: LocalDate): String
}

private fun isLeapYear(year: Int): Boolean {
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
}

val leapOffset = arrayOf(0, 31, 60, 91, 121, 152, 182,
213, 244, 274, 305, 335, 366)
val nonLeapOffset = arrayOf(0, 31, 59, 90, 120, 151, 181,
212, 243, 273, 304, 334, 365)

private fun daysSince2000(year: Int, month: Int, day: Int): Int {

var result = 365 * (year - 2000)
result += ceil((year - 2000) / 4.0).toInt()
result -= ceil((year - 2000) / 100.0).toInt()
result += ceil((year - 2000) / 400.0).toInt()
if (isLeapYear(year)) {
result += leapOffset[month - 1]
} else {
result += nonLeapOffset[month - 1]
}
result += (day - 1)
return result
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class Backend(databaseName: String,
databaseOpener: DatabaseOpener,
fileOpener: FileOpener,
val log: Log,
val dateCalculator: LocalDateCalculator,
val taskRunner: TaskRunner) {

val database: Database
Expand All @@ -56,13 +55,12 @@ class Backend(databaseName: String,
database = databaseOpener.open(dbFile)
database.migrateTo(LOOP_DATABASE_VERSION, fileOpener, log)
habitsRepository = HabitRepository(database)
checkmarkRepository = CheckmarkRepository(database, dateCalculator)
checkmarkRepository = CheckmarkRepository(database)
taskRunner.runInBackground {
habits.putAll(habitsRepository.findAll())
for ((key, habit) in habits) {
val checks = checkmarkRepository.findAll(key)
checkmarks[habit] = CheckmarkList(habit.frequency,
dateCalculator)
checkmarks[habit] = CheckmarkList(habit.frequency)
checkmarks[habit]?.setManualCheckmarks(checks)
}
}
Expand All @@ -76,7 +74,7 @@ class Backend(databaseName: String,
habit.id = id
habit.position = habits.size
habits[id] = habit
checkmarks[habit] = CheckmarkList(habit.frequency, dateCalculator)
checkmarks[habit] = CheckmarkList(habit.frequency)
habitsRepository.insert(habit)
mainScreenDataSource.requestData()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import kotlin.math.*
class CalendarChart(var today: LocalDate,
var color: Color,
var theme: Theme,
var dateCalculator: LocalDateCalculator,
var dateFormatter: LocalDateFormatter) : Component {

var padding = 5.0
Expand All @@ -47,19 +46,19 @@ class CalendarChart(var today: LocalDate,
canvas.setFontSize(height * 0.06)

val nColumns = floor((width - 2 * padding) / squareSize).toInt() - 2
val todayWeekday = dateCalculator.dayOfWeek(today)
val todayWeekday = today.dayOfWeek
val topLeftOffset = (nColumns - 1 + scrollPosition) * 7 + todayWeekday.index
val topLeftDate = dateCalculator.minusDays(today, topLeftOffset)
val topLeftDate = today.minus(topLeftOffset)

repeat(nColumns) { column ->
val topOffset = topLeftOffset - 7 * column
val topDate = dateCalculator.plusDays(topLeftDate, 7 * column)
val topDate = topLeftDate.plus(7 * column)
drawColumn(canvas, column, topDate, topOffset)
}

canvas.setColor(theme.mediumContrastTextColor)
repeat(7) { row ->
val date = dateCalculator.plusDays(topLeftDate, row)
val date = topLeftDate.plus(row)
canvas.setTextAlign(TextAlign.LEFT)
canvas.drawText(dateFormatter.shortWeekdayName(date),
padding + nColumns * squareSize + padding,
Expand All @@ -74,7 +73,7 @@ class CalendarChart(var today: LocalDate,
drawHeader(canvas, column, topDate)
repeat(7) { row ->
val offset = topOffset - row
val date = dateCalculator.plusDays(topDate, row)
val date = topDate.plus(row)
if (offset < 0) return
drawSquare(canvas,
padding + column * squareSize,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ import org.isoron.platform.time.*
class HabitListHeader(private val today: LocalDate,
private val nButtons: Int,
private val theme: Theme,
private val fmt: LocalDateFormatter,
private val calc: LocalDateCalculator) : Component {
private val fmt: LocalDateFormatter) : Component {

override fun draw(canvas: Canvas) {
val width = canvas.getWidth()
Expand All @@ -44,7 +43,7 @@ class HabitListHeader(private val today: LocalDate,
canvas.setFontSize(theme.smallTextSize)

repeat(nButtons) { index ->
val date = calc.minusDays(today, nButtons - index - 1)
val date = today.minus(nButtons - index - 1)
val name = fmt.shortWeekdayName(date).toUpperCase()
val number = date.day.toString()

Expand Down
Loading

0 comments on commit aa6b13f

Please sign in to comment.