# ------------------------------------------------------- # Formatting Timespans # by sovde # # Requires skbee for the `ticks of %timespan%` expression # Can be replaced with your own timespan to ticks method, see line 110 # ------------------------------------------------------- # # This script allows you to format timespans in a similar way to how you can format dates (%date% formatted as "hh:mm:ss"). # the main function is formatTimespan(timespan, format, trim-zeroes). # you give it your timespan, optionally a format string, and optionally a boolean to trim leading zeroes. # # ex: # formatTimespan((1 hour, 1 minute, 1 second)) -> "01:01:01" # # ------------------ # # By default, the format is "hh:mm:ss", but you can change it to whatever you want. (see the on load event if you want to edit the default). # The number of characters in the format string determines the padding of the output. For example, "mm" means that there will always be at least two digits "01", "15", "159", etc. # The script will automatically add more digits as required, but it will never use less digits than what you tell it to. # The default names of the denominations are as follows: # y: year # o: month # w: week # d: day # h: hour # m: minute # s: second # t: millisecond (1 tick = 50 ms) # # You can change these in the on load event as well, just make sure they don't overlap. # # ------------------ # # If you want to add text into the format without it being treated as time symbols, you can use the $ character. # anything within $...$ will be ignored by the script, and will be copied into the output. Doubling the $ will result in a single $ in the output. # # ex: # formatTimespan((1 hour, 1 minute, 1 second), "hh$h$, mm$m$, ss$s left!$") -> "01h, 01m, 01s left!" # # ------------------ # # Finally, trim-zeroes will remove leading zeroes from the output. This is useful if you don't want to show hours if the timespan is less than an hour, for example. # Be warned that this removes *everything* before the first number. If you have text before the first number, it will be removed as well. It will stop at 0.xxx, however, so you can use decimals. # # ex: # formatTimespan((1 minute, 1 second), "hh:mm:ss", true) -> "1:01" # # ------------------ # # If you have any questions, make a post in SkUnity discord and tag me: sovde#0001, but make it clear you're asking about this script! # # To end this off, here's an example of how you could use this script to make a countdown timer: command /cooldown-test : trigger: set {_format} to "mm:ss.tt" while {_cooldown} >= 1 tick: remove 1 tick from {_cooldown} set {_formatted-ts} to formatTimespan({_cooldown}, {_format}, true) send action bar "&7Time until reset: &6%{_formatted-ts}%" to player wait 1 ticks on load: # sets up the tick amounts for each denomination # also sets up the names, feel free to change them, just be careful not to overlap clear {-timespans::*} set {-timespans::1} to ticks of 1 year set {-timespans::1::name} to "y" set {-timespans::2} to ticks of 1 month set {-timespans::2::name} to "o" set {-timespans::3} to ticks of 1 week set {-timespans::3::name} to "w" set {-timespans::4} to ticks of 1 day set {-timespans::4::name} to "d" set {-timespans::5} to ticks of 1 hour set {-timespans::5::name} to "h" set {-timespans::6} to ticks of 1 minute set {-timespans::6::name} to "m" set {-timespans::7} to ticks of 1 second set {-timespans::7::name} to "s" set {-timespans::8} to 1 set {-timespans::8::name} to "t" # sets the default format string, feel free to change it # it's used if you don't specify a format string in the formatTimespan function set {-timespan-default-format} to "hh:mm:ss" # Accepts a timespan, a format string, and a boolean to trim leading zeroes # Returns a string with the timespan formatted according to the format string # # Parameters: # timespan: the timespan to format # format: the format string to use. Defaults to the default format string, which is "hh:mm:ss" # trim-zeroes: whether or not to trim leading zeroes. Defaults to false function formatTimespan(timespan: timespan, format: string = {-timespan-default-format}, trim-zeroes: boolean = false) :: string: # handle non-placeholder characters: set {_escaped::*} to timespanGetEscapedCharacters({_format}) set {_format} to join (regex split {_format} at "\$.*?\$") with "$" set {_format} to lowercase {_format} set {_ticks} to ticks of {_timespan} # requires SkBee. Replace with your own timespan to ticks method if you don't have SkBee, like .getTicks() for skript-reflect. # for each denomination, replace the placeholder with the correct amount of ticks # then remove the amount of ticks from the total loop {-timespans::*}: if {_format} contains {-timespans::%loop-index%::name}: set {_timespan} to floor({_ticks} / {-timespans::%loop-index%}) set {_ticks} to mod({_ticks}, {-timespans::%loop-index%}) set {_format} to timespanReplaceFormat({_format}, {-timespans::%loop-index%::name}, {_timespan}) # handle non-placeholder characters: loop {_escaped::*}: replace first "$" with {_escaped::%loop-index%} in {_format} # trim zeros # it's kinda hacky, just looks for the first non-zero character and cuts off everything before it # keeps decimals, so you can use 0.00 to show milliseconds if {_trim-zeroes} is true: set {_start} to length of {_format} + 1 loop length of {_format} times: if character at loop-value of {_format} matches "[1-9]": set {_start} to loop-value exit loop else if character at loop-value of {_format} is "0": character at loop-value + 1 of {_format} is "." character at loop-value + 2 of {_format} matches "\d" set {_start} to loop-value exit loop # cut off everything before the first non-zero character set {_format} to substring of {_format} from {_start} to length of {_format} return {_format} # replaces all characters between the first and last occurrence of the given name in the format string with the padded value # returns the new format string # # Parameters: # format: the format string to replace characters in # name: the name of the denomination to replace # value: the number to replace the characters with function timespanReplaceFormat(format: string, name: string, value: number) :: string: set {_first} to first index of {_name} in {_format} set {_last} to last index of {_name} in {_format} set {_length} to {_last} - {_first} + 1 if {_name} is "t": set {_value} to {_value} / 20 set {_replaceValue} to timespanPadValue({_value}, {_length}) replace substring of {_format} from {_first} to {_last} with {_replaceValue} in {_format} return {_format} # pads the given value to the given length with 0s # returns the padded value # # Parameters: # value: the value to pad # length: the length to pad to function timespanPadValue(value: number, length: number) :: string: # handle decimal values (ticks) set {_decimals} to mod({_value}, 1) set {_value} to floor({_value}) # pad decimals to 2 digits (ticks are multiples of 0.05) if {_decimals} is not 0: set {_decimals} to floor({_decimals} * 100) set {_decimal-value} to timespanPadValue({_decimals}, 2) # add non-zero parts if {_decimal-value} is set: set {_final-value} to "%{_value}%." if {_value} is not 0 else "" set {_final-value} to "%{_final-value}%%{_decimal-value}%" else: set {_final-value} to "%{_value}%" # pad left with 0s while length of {_final-value} < {_length}: set {_final-value} to "0%{_final-value}%" if {_decimal-value} is not set else "%{_final-value}%0" return {_final-value} # returns a list of all substrings that are escaped (via $) in the given string # # Parameters: # format: the format string to get escaped characters from function timespanGetEscapedCharacters(format: string) :: strings: set {_chars::*} to {_format} split at "" set {_escaped} to false # iterate over list, toggle escaped state at $, add to escaped list if escaped loop {_chars::*}: if loop-value is "$": set {_escaped} to true if {_escaped} is false else false if {_escaped} is true: add 1 to {_counter} continue if {_escaped} is true: set {_escaped::%{_counter}%} to "%{_escaped::%{_counter}%} ? ""%%loop-value%" return {_escaped::*}