ID:1136789
 
I don't expect anyone to use this, I made this a while ago in a request from Kidpaddle45 and felt like sharing it for the community.

#define INVERTED 1
#define NORMAL 0

var/Timer/MyDate = new(23,59,30,29,11,2013,0)

Timer


var
Mode

Seconds = 0
Minutes = 0
Hours = 0

// New implementation, Months and Years
Day = 1
Month = 1
Year = 1

New(h=0, m=0, s=0, day=1, month=1, year=1, mode = NORMAL)
.=..()

Hours = h
Minutes = m
Seconds = s
Day = day
Month = month
Year = year
Mode = mode

doTime()

proc/doTime()

if(Mode == INVERTED) spawn while(1)
if(!Seconds && !Minutes && !Hours)
del src // Why delete the timer? This inverted timer was designed as a cooldown handler.
// so it can be accessed in many ways; if(src.cooldown)return, for example.

if(--Seconds == 0)
if(--Minutes > -1)
Seconds = 60
if(!Minutes && --Hours > -1)
Minutes = 60
sleep(10)

else if(Mode == NORMAL) spawn while(1)
if(++Seconds >= 60)
Seconds = 0
if(++Minutes >= 60)
Minutes = 0
if(++Hours >= 24)
Hours = 0
var needDays = Month % 2
if(++Day >= (needDays ? 31 : 30))
Day = 1
if(++Month >= 13)
Month = 1
Year++
world << "[Hours<10? "0[Hours]":"[Hours]"]:[Minutes<10? "0[Minutes]":"[Minutes]"]:[Seconds<10? "0[Seconds]":"[Seconds]"] - [Day<10? "0[Day]":"[Day]"], [Month<10? "0[Month]":"[Month]"] [Year]"
sleep(10)


Maybe this is not the best way of handling this, I would also want to know your opinions.
I think you just could compare 2 times. (Using built-in time2text and those functions)
Uhm basically yes you could. But you would require to call time2text multiple times depending what is required.

I guess accessing an auto-inceremnting variable within a global variable is much more easier to work with, at least it is what I intended.

Also, it is a bit messy to work with time2text with cooldowns, I'd rater work with world.time and use ticks.
In response to Fushimi
Fushimi wrote:
Uhm basically yes you could. But you would require to call time2text multiple times depending what is required.

I guess accessing an auto-inceremnting variable within a global variable is much more easier to work with, at least it is what I intended.

Also, it is a bit messy to work with time2text with cooldowns, I'd rater work with world.time and use ticks.

Do not ever rely on a additive counter for a timer, it will just cause you pain and headaches later on.

Use time stamps and subtraction.
For most of my needs world.time, realtime and timeofday suit just fine, pros being that they are reliable and unhindered by other processes causing freezes or slowdowns. They're useful for timing how long intensive processes take to complete, or for measuring much longer intervals, etc.

However, an approach like yours is definitely better when you want to continuously keep track of each individual unit. As an extra touch, it would be nice to have lists defining the limit and name for each unit plus some other customizations. Here's my take: (I'll post inverted later)

ticker
var/units[] // unit quantity definitions
var/measure[] // measurements being taken

var/ticking =0
var/delay =10

New()
.=..()
reset()

proc
reset() measure = list()
unit(u) return measure&&measure[u] // how many of something has been measured so far

tick()
for(var/u in units)
measure[u]++
if(measure[u]>=units[u])
measure[u]-=units[u]
continue
else break

start()
if(ticking) return
ticking=1
spawn while(ticking)
sleep(delay)
tick()

stop() ticking=0

toggle()
// convenience proc
if(ticking) stop()
else start()

clock
parent_type = /ticker
delay = 10

units = list("second"=60,"minute"=60,"hour"=24,"day"=1#INF)

var/clock/test
client/verb/toggle_test()
if(!test) test=new
test.toggle()
src << "Ticker [test.ticking?"started":"stopped"]."

client/verb/time()
if(test)
for(var/u in test.measure)
src << "[u]s: [test.unit(u)]"