AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

nearest time-unit
Goto page 1, 2  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
Ace_NoOne



Joined: 10 Oct 2005
Posts: 333
Location: Germany

PostPosted: Thu Jul 12, 2007 9:21 am    Post subject: nearest time-unit Reply with quote

Hey guys,

For my Progress Timer, I wanna make the start date optional - which means that to display the relative progress (percentage), I have to calculate an appropriate start date automatically.

Here's my concept for this, and I'd love to hear some feedback - and maybe even get some help with the implementation (I hate time calculations... ):

The end date (C) is known, as is the current time (B) - and thus I also know the time that's left (x = C - B):
Code:
  |_____________________|
  |          |    =x    |
  A          B          C
start       now        end
Knowing x allows me to select an appropriate time unit (or scale); minutes, hours, days, weeks, months, years, decades, centuries, or millennia.
Once I know that, I can calculate the start date based on that unit:
Code:
0         <= x < 1 min.         =>    A = C - 1 min.
1 min.    <= x < 1 hour         =>    A = C - 1 hour
1 hour    <= x < 1 day          =>    A = C - 1 day
1 day     <= x < 1 week         =>    A = C - 1 week
1 week    <= x < 1 month        =>    A = C - 1 month
1 month   <= x < 1 year         =>    A = C - 1 year
1 year    <= x < 1 decade       =>    A = C - 1 decade
1 decade  <= x < 1 century      =>    A = C - 1 century
1 century <= x < 1 millenium    =>    A = C - 1 millenium
             x >= 1 millenium   =>    ERROR: Get a life...

As for the implementation, that would have to be a function that's passed a single date (two if you count A_Now) and returns the appropriate start date.
But I'm not yet sure how to implement this efficiently (i.e. without a lot of nested IF statements).

Any feedback is appreciated!
_________________
Improving my world, one script at a time.
Join the AutoHotkey IRC channel: irc.freenode.net #autohotkey
Back to top
View user's profile Send private message
Seabiscuit



Joined: 07 Jan 2007
Posts: 109
Location: In fund pe scaun, la o bere prin Romania :D

PostPosted: Thu Jul 12, 2007 2:34 pm    Post subject: Reply with quote

Do you need a very precise function in calculating months between two dates or a rough one? Cause those days can be real pain in the ass.
_________________
Backgammon addicted!
GamesGrid was one of the first online web sites to bring Backgammon to the Internet


Last edited by Seabiscuit on Thu Jul 12, 2007 2:40 pm; edited 1 time in total
Back to top
View user's profile Send private message Yahoo Messenger
Ace_NoOne



Joined: 10 Oct 2005
Posts: 333
Location: Germany

PostPosted: Thu Jul 12, 2007 2:37 pm    Post subject: Reply with quote

To be honest, I'm not quite sure what you mean.

Also, shouldn't EnvAdd take care of the actual calculations?
_________________
Improving my world, one script at a time.
Join the AutoHotkey IRC channel: irc.freenode.net #autohotkey
Back to top
View user's profile Send private message
Seabiscuit



Joined: 07 Jan 2007
Posts: 109
Location: In fund pe scaun, la o bere prin Romania :D

PostPosted: Thu Jul 12, 2007 2:40 pm    Post subject: Reply with quote

I've corected myself, I was talking about months.
_________________
Backgammon addicted!
GamesGrid was one of the first online web sites to bring Backgammon to the Internet
Back to top
View user's profile Send private message Yahoo Messenger
Ace_NoOne



Joined: 10 Oct 2005
Posts: 333
Location: Germany

PostPosted: Thu Jul 12, 2007 2:41 pm    Post subject: Reply with quote

Oh, right; 30 days per month would be just fine.
_________________
Improving my world, one script at a time.
Join the AutoHotkey IRC channel: irc.freenode.net #autohotkey
Back to top
View user's profile Send private message
engunneer



Joined: 30 Aug 2005
Posts: 6772
Location: Pacific Northwest, US

PostPosted: Thu Jul 12, 2007 3:28 pm    Post subject: Reply with quote

I will think about this as I drive to work - A nested If is not such a bad thing.
_________________
Unless otherwise noted, all code is untested.
Common Answers: 1.(Loops, Viruses, etc.) 2. Search 3.RTFM
Back to top
View user's profile Send private message Visit poster's website
Seabiscuit



Joined: 07 Jan 2007
Posts: 109
Location: In fund pe scaun, la o bere prin Romania :D

PostPosted: Thu Jul 12, 2007 4:16 pm    Post subject: Reply with quote

Try this and tell me if its not ok.
Code:
C=20171012185312
msgbox % scale(c)

scale(c){
   c-=%a_now%,seconds
   sc=31104000000/3110400000/311040000/31104000/2592000/604800/86400/3600/60
   x=
   Loop, parse, sc, /
   {
      if ((c-A_LoopField)>=0){
         x:=A_Index
         break
      }
   }
   sc=millenium(s)/century(s)/decade(s)/year(s)/month(s)/week(s)/day(s)/hour(s)/minunte(s)
   Loop, parse, sc, /
   {
       if (A_Index=x){
         result=%A_LoopField%
         break
      }
   }
return result
}

_________________
Backgammon addicted!
GamesGrid was one of the first online web sites to bring Backgammon to the Internet
Back to top
View user's profile Send private message Yahoo Messenger
Ace_NoOne



Joined: 10 Oct 2005
Posts: 333
Location: Germany

PostPosted: Thu Jul 12, 2007 8:20 pm    Post subject: Reply with quote

That's a very interesting approach, Seabiscuit!

There seems to be bug though - consider this script:
Code:
results := "results:`n`n"

time := A_Now
time += 30, Seconds
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 30, Minutes
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 12, Hours
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 1, days
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 15, days
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 180, days
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 1800, days
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 18000, days
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 180000, days
results .= time . ": " . scale(time) . "`n"

MsgBox %results%

Return

scale(c){
   c-=%a_now%,seconds
   sc=31104000000/3110400000/311040000/31104000/2592000/604800/86400/3600/60
   x=
   Loop, parse, sc, /
   {
      if ((c-A_LoopField)>=0){
         x:=A_Index
         break
      }
   }
   sc=millenium(s)/century(s)/decade(s)/year(s)/month(s)/week(s)/day(s)/hour(s)/minunte(s)
   Loop, parse, sc, /
   {
       if (A_Index=x){
         result=%A_LoopField%
         break
      }
   }
return result
}

The first run returns nothing. I haven't been able to figure out why yet (as I've said, I hate time calculations... ).
_________________
Improving my world, one script at a time.
Join the AutoHotkey IRC channel: irc.freenode.net #autohotkey
Back to top
View user's profile Send private message
Titan



Joined: 11 Aug 2004
Posts: 5068
Location: imaginationland

PostPosted: Thu Jul 12, 2007 8:52 pm    Post subject: Reply with quote

Instead of using scales why not have everything timed in seconds, and update the progress bar at dynamic intervals such that it equates to a percent increase every time.
_________________

RegExReplace("irc.freenode.net/ahk", "^(?=(.(?=[\0-r\[]*((?<=\.).))))(?:[c-\x73]{2,8}(\S))+((2)|\b[^\2-]){2}\D++$", "$u3$1$3$4$2")
Back to top
View user's profile Send private message Visit poster's website
Ace_NoOne



Joined: 10 Oct 2005
Posts: 333
Location: Germany

PostPosted: Thu Jul 12, 2007 9:27 pm    Post subject: Reply with quote

Well, Titan, I'll give you an example:

Say I'm going on vacation in a few weeks.

So I add the Progress Timer to the Windows startup folder to get an update every morning (which I'd close right after having taken a look at it).
Setting a start date there doesn't make much sense, obviously - and neither does what you propose (if I understand it correctly, that is).

With the method outlined above, we could gradually "zoom in" on the timescale as the event draws closer:
First I'd get a percentage based on a months-scale, then on a weeks-scale, etc. (never reaching 100% though, as changing the scale resets the progress bar) - until eventually I can pretty much watch the progress bar advance towards the yearned-for 100%...

(I hope this makes sense!?)
_________________
Improving my world, one script at a time.
Join the AutoHotkey IRC channel: irc.freenode.net #autohotkey
Back to top
View user's profile Send private message
Seabiscuit



Joined: 07 Jan 2007
Posts: 109
Location: In fund pe scaun, la o bere prin Romania :D

PostPosted: Fri Jul 13, 2007 1:54 am    Post subject: Reply with quote

Put 0 instead of 60.
Code:
results := "results:`n`n"

time := A_Now
time += 30, Seconds
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 30, Minutes
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 12, Hours
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 1, days
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 15, days
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 180, days
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 1800, days
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 18000, days
results .= time . ": " . scale(time) . "`n"

time := A_Now
time += 180000, days
results .= time . ": " . scale(time) . "`n"

MsgBox %results%

Return

scale(c){
   c-=%a_now%,seconds
   sc=31104000000/3110400000/311040000/31104000/2592000/604800/86400/3600/0
   x=
   Loop, parse, sc, /
   {
      if ((c-A_LoopField)>=0){
         x:=A_Index
         break
      }
   }
   sc=millenium(s)/century(s)/decade(s)/year(s)/month(s)/week(s)/day(s)/hour(s)/minunte(s)
   Loop, parse, sc, /
   {
       if (A_Index=x){
         result=%A_LoopField%
         break
      }
   }
return result
}

Wink
_________________
Backgammon addicted!
GamesGrid was one of the first online web sites to bring Backgammon to the Internet
Back to top
View user's profile Send private message Yahoo Messenger
Ace_NoOne



Joined: 10 Oct 2005
Posts: 333
Location: Germany

PostPosted: Sat Jul 14, 2007 3:12 pm    Post subject: Reply with quote

After quite a few test runs, I'm still not sure whether that really fixed the problem.

I've modified the function to return the respective start date (the date passed to the function minus the nearest unit/interval), and I've also done some refactoring (code includes a short test script):
Code:
results := "results:`n`n"

time := A_Now
time += 30, Seconds
results .= time . ": " . timescale(time) . "`n"

time := A_Now
time += 30, Minutes
results .= time . ": " . timescale(time) . "`n"

time := A_Now
time += 12, Hours
results .= time . ": " . timescale(time) . "`n"

time := A_Now
time += 1, days
results .= time . ": " . timescale(time) . "`n"

time := A_Now
time += 15, days
results .= time . ": " . timescale(time) . "`n"

time := A_Now
time += 180, days
results .= time . ": " . timescale(time) . "`n"

time := A_Now
time += 1800, days
results .= time . ": " . timescale(time) . "`n"

time := A_Now
time += 18000, days
results .= time . ": " . timescale(time) . "`n"

time := A_Now
time += 180000, days
results .= time . ": " . timescale(time) . "`n"

MsgBox %results%

Return

; timescale() by Seabiscuit, modified by FND
timescale(date) {
   ; initialize
   time := date
   timeIntervals = 31104000000|3110400000|311040000|31104000|2592000|604800|86400|3600|0
   timeUnits = millenium(s)|century(s)|decade(s)|year(s)|month(s)|week(s)|day(s)|hour(s)|minunte(s)
   index = ; DEBUG: obsolete!?
   match = ; DEBUG: obsolete!?
   result = ; DEBUG: obsolete!?
   ; calculate time left
   time -= %A_Now%, Seconds
   ; find nearest unit
   Loop, Parse, timeIntervals, |
   {
      if((time - A_LoopField) >= 0) {
         index := A_Index ; DEBUG: obsolete!?
         match := A_LoopField
         Break
      }
   }
   ; assign unit -- DEBUG: obsolete!?
   Loop, Parse, timeUnits, |
   {
       If(A_Index = index) {
         result .= A_LoopField
         Break
      }
   }
   ; calculate start date
   startDate := date
   startDate += -match, Seconds
   result .= "`n" . startDate . "`n" ; DEBUG: obsolete!?
   ; return start date
   Return result ; DEBUG: only return startDate!?
}
Seems buggy though... Confused
_________________
Improving my world, one script at a time.
Join the AutoHotkey IRC channel: irc.freenode.net #autohotkey
Back to top
View user's profile Send private message
Titan



Joined: 11 Aug 2004
Posts: 5068
Location: imaginationland

PostPosted: Sun Jul 15, 2007 7:12 pm    Post subject: Reply with quote

Code:
TimeScale(c) {
   static y1, y2, d = "-", f
      , s1 = "Millenia", s2 = "Centuries", s3 = "Years", s4 = "Months"
      , s5 = "Days", s6 = "Hours", s7 = "Minutes", s8 = "Seconds"
      , s9 = "Now", s10 = "Decades", s11 = "Weeks"
   If y1 =
   {
      f = yy%d%MM%d%dd%d%HH%d%mm%d%ss
      FormatTime, y, , yyyy
      StringLeft, y, y, 2
      StringSplit, y, y
   }
   FormatTime, n, , %f%
   n = %y1%%d%%y2%%d%%n%
   StringSplit, n, n, %d%
   FormatTime, cy, %c%, yyyy
   FormatTime, c, %c%, %f%
   StringLeft, cy, cy, 2
   StringSplit, cy, cy
   c = %cy1%%d%%cy2%%d%%c%
   Loop, Parse, c, %d%
      If (A_LoopField > n%A_Index%) {
         If A_Index = 5
         {
            If (A_LoopField - n%A_Index%) > 7
               Return, s11
         }
         Else If A_Index = 3
         {
            If (A_LoopField - n%A_Index%) > 10
               Return, s10
         }
         Return, s%A_Index%
      }
   Return, s9
}

Hope this helps.
_________________

RegExReplace("irc.freenode.net/ahk", "^(?=(.(?=[\0-r\[]*((?<=\.).))))(?:[c-\x73]{2,8}(\S))+((2)|\b[^\2-]){2}\D++$", "$u3$1$3$4$2")
Back to top
View user's profile Send private message Visit poster's website
Ace_NoOne



Joined: 10 Oct 2005
Posts: 333
Location: Germany

PostPosted: Mon Jul 16, 2007 9:11 am    Post subject: Reply with quote

I'm afraid your script is buggy, Titan; it returns different values at different times.

Take my (updated) test script:
Code:
results := FormatTime(A_Now) . ": now`n"

time := A_Now
time += 30, Seconds
results .= FormatTime(time) . ": " . TimeScale(time) . "`n"

time := A_Now
time += 30, Minutes
results .= FormatTime(time) . ": " . TimeScale(time) . "`n"

time := A_Now
time += 12, Hours
results .= FormatTime(time) . ": " . TimeScale(time) . "`n"

time := A_Now
time += 1, days
results .= FormatTime(time) . ": " . TimeScale(time) . "`n"

time := A_Now
time += 15, days
results .= FormatTime(time) . ": " . TimeScale(time) . "`n"

time := A_Now
time += 180, days
results .= FormatTime(time) . ": " . TimeScale(time) . "`n"

time := A_Now
time += 1800, days
results .= FormatTime(time) . ": " . TimeScale(time) . "`n"

time := A_Now
time += 18000, days
results .= FormatTime(time) . ": " . TimeScale(time) . "`n"

time := A_Now
time += 180000, days
results .= FormatTime(time) . ": " . TimeScale(time) . "`n"

MsgBox %results%

Return

FormatTime(str) {
    FormatTime, str, %str%, yyyy-MM-dd hh:mm:ss
    Return str
}

; TimeScale() by Titan
TimeScale(c) {
   static y1, y2, d = "-", f
      , s1 = "Millenia", s2 = "Centuries", s3 = "Years", s4 = "Months"
      , s5 = "Days", s6 = "Hours", s7 = "Minutes", s8 = "Seconds"
      , s9 = "Now", s10 = "Decades", s11 = "Weeks"
   If y1 =
   {
      f = yy%d%MM%d%dd%d%HH%d%mm%d%ss
      FormatTime, y, , yyyy
      StringLeft, y, y, 2
      StringSplit, y, y
   }
   FormatTime, n, , %f%
   n = %y1%%d%%y2%%d%%n%
   StringSplit, n, n, %d%
   FormatTime, cy, %c%, yyyy
   FormatTime, c, %c%, %f%
   StringLeft, cy, cy, 2
   StringSplit, cy, cy
   c = %cy1%%d%%cy2%%d%%c%
   Loop, Parse, c, %d%
      If (A_LoopField > n%A_Index%) {
         If A_Index = 5
         {
            If (A_LoopField - n%A_Index%) > 7
               Return, s11
         }
         Else If A_Index = 3
         {
            If (A_LoopField - n%A_Index%) > 10
               Return, s10
         }
         Return, s%A_Index%
      }
   Return, s9
}
The first two values returned by your function (i.e. rows 2 and 3) are sometimes Seconds/Minutes, at other times it's Minutes/Minutes, and at around 10:00 o'clock just now I even had Hours/Hours (if I recall correctly, that is).

As you know, I usually have a hard time understanding your code, so I can't quite figure out how to make that function return the actual start date (see above)...

Anyway, I appreciate all your efforts!
_________________
Improving my world, one script at a time.
Join the AutoHotkey IRC channel: irc.freenode.net #autohotkey
Back to top
View user's profile Send private message
Titan



Joined: 11 Aug 2004
Posts: 5068
Location: imaginationland

PostPosted: Mon Jul 16, 2007 9:56 am    Post subject: Reply with quote

Yes I know, 60+ seconds adds a minute which could increase the hour interval and so on. I thought the method would be more accurate in terms of months and leap years but unfortunately it has this problem. Building on SeaBiscuit's method:

Code:
TimeScale(c) {
   static i = "31104000000,3110400000,311040000,31104000,2592000,604800,86400,3600,60,1"
      , u = "Millenia,Centuries,Decades,Years,Months,Weeks,Days,Hours,Minutes,Seconds,Now"
   c -= A_Now, s
  StringSplit, u, u, `,
  Loop, Parse, i, `,
     If c >= %A_LoopField%
        Return, u%A_Index%
   Return, u11
}

_________________

RegExReplace("irc.freenode.net/ahk", "^(?=(.(?=[\0-r\[]*((?<=\.).))))(?:[c-\x73]{2,8}(\S))+((2)|\b[^\2-]){2}\D++$", "$u3$1$3$4$2")
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group