Time
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Electrified

// @version=5
// @description Utilities for measuring time.
library("Time")

///////////////////////////////////////////////////
// @function Gets the number of milliseconds per bar.
export bar() =>
    var int msPerDay = 1000 * 60 * 60 * 24
    var int m = switch
        timeframe.isdaily => msPerDay
        timeframe.isweekly => msPerDay * 7
        timeframe.ismonthly => msPerDay * 30
        timeframe.isseconds => 1000
        timeframe.isminutes => 1000 * 60
        => na
    var value = m * timeframe.multiplier
    value
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function Gets the start of the day for the provided time value.
// @param datetime The date/time to acquire the date from.
// @returns The number of milliseconds representing the date for the given value.
export date(int datetime = time) =>
    timestamp(year(datetime), month(datetime), dayofmonth(datetime))
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function Gets milliseconds from the start of the day.
// @param datetime The date/time to acquire the time of day from.
// @returns The number of milliseconds representing time of day.
export timeOfDay(int datetime = time) =>
    datetime - date(datetime)
///////////////////////////////////////////////////

// Normalizes timespan and timeframe values.
adjustTimeframe(simple float timespan, simple string type) =>
    var typeLower = str.lower(type)
    var ts = switch typeLower
        'bar' => 'bars'
        'second' => 'seconds'
        'minute' => 'minutes'
        'day' => 'days'
        'week' => 'weeks'
        'month' => 'months'
        'year' => 'years'
        => typeLower

    var dayMultiple = switch ts
        'weeks' => 7
        'months' => 30
        'years' => 365
        => 1

    var t = dayMultiple == 1 ? ts : 'days'
    var s = timespan * dayMultiple
    [s,t]

///////////////////////////////////////////////////
// @function Returns the number (float) bars that represents the timespan provided.
// @param timespan The number of units to convert to bar count.
// @param type The type of units to measure. ('Bar', 'Bars', 'Minute', 'Minutes', 'Day' or 'Days')
// @param sessionMinutes Optional override for the number of minutes per session.  (Default: Regular = 390, Extended = 1440)
// @returns The number bars that represents the timespan provided.
export spanToLen(simple float timespan, simple string type, simple int sessionMinutes = na) =>
    var sess_minutes = na(sessionMinutes) ? syminfo.session == session.regular ? 390 : 1440 : sessionMinutes
    var float minutesPerBar = switch
        timeframe.isminutes => timeframe.multiplier
        timeframe.isseconds => timeframe.multiplier / 60
        timeframe.isdaily => sess_minutes
        timeframe.isweekly => sess_minutes * 7
        timeframe.ismonthly => sess_minutes * 30
        => na

    [s, t] = adjustTimeframe(timespan, type)

    switch t
        'bars' => s
        'seconds' => s / minutesPerBar
        'minutes' => s / minutesPerBar
        'days' => timeframe.isintraday ?
          (sess_minutes * s / minutesPerBar) :
          timeframe.isdaily ? s :
          timeframe.isweekly ? s / 7 : 
          timeframe.ismonthly ? s / 30 :
          na          
        => na
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function Returns the number (int) bars that represents the timespan provided.
// @param timespan The number of units to convert to bar count.
// @param type The type of units to measure. ('Bar', 'Minute' or 'Day')
// @returns The number bars that represents the timespan provided.
export spanToIntLen(simple float timespan, simple string type) =>
    math.ceil(spanToLen(timespan, type))
///////////////////////////////////////////////////

plot(bar())