All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.maddy.calendar.core.Helpers.kt Maven / Gradle / Ivy

package com.maddy.calendar.core

object Math {
    fun floorDiv(x: Long, y: Long): Int {
        var r = x / y
        // if the signs are different and modulo not zero, round down
        if (x xor y < 0 && r * y != x) {
            r--
        }
        return r.toInt()
    }

    fun floorMod(x: Long, y: Long): Long {
        return x - floorDiv(x, y) * y
    }

    fun addExact(x: Long, y: Long): Long {
        val r: Long = x + y
        return if (x xor r and (y xor r) < 0L) {
            throw ArithmeticException("long overflow")
        } else {
            r
        }
    }
}

object Period {

    fun weeksBetween(
        start: ILocalDate,
        end: ILocalDate,
        firstDayOfWeek: DayOfWeek = DayOfWeek.SUNDAY
    ): Int {
        val (isNegative, startEnd) = startEndType(start, end)
        val (earlyDate, laterDate) = startEnd

        var totalDays = daysBetween(earlyDate, laterDate) + 1

        if (totalDays <= 1L){
            return 1
        }

        val startDayOfWeek = earlyDate.dayOfWeek
        val dom = (firstDayOfWeek - startDayOfWeek).value
        var count = 0
        if (dom > 0){
            count++
            totalDays-=dom
        }

        val fullWeeks = (totalDays/7).toInt()
        val remDays = totalDays%7
        count += fullWeeks
        if (remDays > 0){
            count++
        }
        return count * isNegative
    }

    fun monthsBetween(start: ILocalDate, end: ILocalDate): Int {
        if (start == end) {
            return 0
        }

        val (isNegative, startEnd) = startEndType(start, end)
        val (earlyDate, laterDate) = startEnd

        val yearDifference = laterDate.year - earlyDate.year - 1
        var dom = yearDifference * Month.DECEMBER_CHAITRA.value
        dom += (Month.DECEMBER_CHAITRA - earlyDate.month).value + laterDate.monthValue
        return dom * isNegative
    }

    fun daysBetween(start: ILocalDate, end: ILocalDate): Long {
        if (start == end) {
            return 0
        }

        val (isNegative, startEnd) = startEndType(start, end)
        val (earlyDate, laterDate) = startEnd

        if (earlyDate.year == laterDate.year) {
            return (laterDate.dayOfYear - earlyDate.dayOfYear).toLong()
        }

        var dom: Long = 0
        for (year in (earlyDate.year + 1) until laterDate.year) {
            dom += ILocalDate.Utils.lengthOfYear(year, earlyDate.type)
        }

        dom += earlyDate.lengthOfYear - earlyDate.dayOfYear
        dom += laterDate.dayOfYear
        return dom * isNegative
    }

    internal fun startEndType(
        start: ILocalDate,
        end: ILocalDate
    ): Pair> {
        val toS = if (start.type != end.type) {
            end.reverse()
        } else end.copy()

        val fromDate: ILocalDate
        val toDate: ILocalDate

        val isNegative = when {
            start == toS -> {
                fromDate = start.copy()
                toDate = toS
                1
            }
            start < toS -> {
                fromDate = start.copy()
                toDate = toS
                1
            }
            else -> {
                fromDate = toS
                toDate = start.copy()
                -1
            }
        }
        return isNegative to (fromDate to toDate)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy