mIRC Home    About    Download    Register    News    Help

Print Thread
Page 1 of 2 1 2
Making $duration include months/years #126250 26/07/05 11:32 PM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Ok, I'd like opinions/thoughts on this script I just wrote in the last hour or so. The script should accurately output a $duration with months/years as long as the $duration is from the current date to some other past date (like when calculating uptime). I could probably make it also go forwards, but that is beyond what I'm trying to do with it right now.

Note that no matter what the $duration is (whether it's from today's date and counting backwards, or some other way), it will still be very accurate (within a few days at most). It just can't be guaranteed to be perfectly accurate except when using the current date and going backwards.

After I have your comments and ideas (and any bugs) about the script and its usefulness, I'll see about submitting it to mircscripts.org. Also, feel free to suggest fixes to the code to make it better.

Code:
; *******************************************************************
; DateXpander Script
; by Riamus 2005
;
; This script will take a standard $duration and make it include months and years
; based on the current date.
;
; For this script to be accurate, it is only meant to be used when the $duration is
; using today's date and counting backwards (such as an uptime $duration).  It
; will still be really accurate (within 3 days) even if you use a $duration that isn't
; from the current date, but it won't be exact that way.
;
; Use: $DateXpander(value)
; "value" must be in the format of $duration
;
; For questions about this script, contact Riamus on IRC -- #oldgames on irc.undernet.org
; *******************************************************************

alias DateXpander {
  unset %dateoutput

  set %weeks $iif($gettok($1-,1,119) isnum,$gettok($1-,1,119),0)
  set %days $iif($gettok($gettok($1-,1,100),-1,32) isnum,$gettok($gettok($1-,1,100),-1,32),0)
  set %hours $iif($gettok($gettok($1-,1,104),-1,32) isnum,$gettok($gettok($1-,1,104),-1,32),0)
  set %minutes $iif($gettok($gettok($1-,1,109),-1,32) isnum,$gettok($gettok($1-,1,109),-1,32),0)
  set %seconds $iif(sec isin $gettok($1-,$gettok($1-,0,32),32),$gettok($gettok($1-,$gettok($1-,0,32),32),1,115),0)
  set %totaldays $calc(%weeks * 7 + %days)
  if (%weeks < 4) {
    goto yearstart
  }

  set %currentmonth $date(m)

  :monthstart
  if (%currentmonth == 12) {
    if (%totaldays > 29) {
      inc %months
      dec %totaldays 30
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 11) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 10) {
    if (%totaldays > 29) {
      inc %months
      dec %totaldays 30
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 9) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 8) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 7) {
    if (%totaldays > 29) {
      inc %months
      dec %totaldays 30
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 6) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 5) {
    if (%totaldays > 29) {
      inc %months
      dec %totaldays 30
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 4) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 3) {
    if (%totaldays > 27 && $int($calc($year / 4) != $calc($year / 4))) {
      inc %months
      dec %totaldays 28
      dec %currentmonth
    }
    elseif (%totaldays > 28 && $int($calc($year / 4) == $calc($year / 4))) {
      inc %months
      dec %totaldays 29
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 2) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 1) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      set %currentmonth 12
    }
    else { goto yearstart }
  }
  goto monthstart

  :yearstart
  set %years $int($calc(%months / 12))
  dec %months $calc(%years * 12)
  set %weeks $int($calc(%totaldays / 7))
  set %totaldays $calc(%totaldays - (%weeks * 7))

  if (%years > 1) { set %dateoutput %dateoutput %years $+ _years }
  elseif (%years == 1) { set %dateoutput %dateoutput %years $+ _year }
  if (%months > 1) { set %dateoutput %dateoutput %months $+ _months }
  elseif (%months == 1) { set %dateoutput %dateoutput %months $+ _month }
  if (%weeks > 1) { set %dateoutput %dateoutput %weeks $+ _weeks }
  elseif (%weeks == 1) { set %dateoutput %dateoutput %weeks $+ _week }
  if (%totaldays > 1) { set %dateoutput %dateoutput %totaldays $+ _days }
  elseif (%totaldays == 1) { set %dateoutput %dateoutput %totaldays $+ _day }
  if (%hours > 1) { set %dateoutput %dateoutput %hours $+ _hours }
  elseif (%hours == 1) { set %dateoutput %dateoutput %hours $+ _hour }
  if (%minutes > 1) { set %dateoutput %dateoutput %minutes $+ _minutes }
  elseif (%minutes == 1) { set %dateoutput %dateoutput %minutes $+ _minute }
  if (%seconds > 1) { set %dateoutput %dateoutput %seconds $+ _seconds }
  elseif (%seconds == 1) { set %dateoutput %dateoutput %seconds $+ _second }

  unset %years
  unset %months
  unset %weeks
  unset %days
  unset %hours
  unset %minutes
  unset %seconds
  unset %totaldays
  unset %currentmonth

  return $replace(%dateoutput,$chr(32),$chr(44) $+ $chr(32),_,$chr(32))
}


Just as one explanation to how this works so you don't start saying it's messing up for it...

The current month is July. If you go back to the same date last month, you are going back 30 days (June has 30 days). That's one month ago.

So, some examples:

$datexpander(3wks 6days)
3 weeks, 6 days

$datexpander(4wks)
4 weeks

$datexpander(4wks 1day)
4 weeks, 1 day

$datexpander(4wks 2days)
1 month

$datexpander(4wks 3days)
1 month, 1 day


Invision Support
#Invision on irc.irchighway.net
Re: Making $duration include months/years #126251 27/07/05 01:16 AM
Joined: Aug 2004
Posts: 7,252
R
RusselB Offline
Hoopy frood
Offline
Hoopy frood
R
Joined: Aug 2004
Posts: 7,252
I can't remember where I got this code from and I know I didn't write it. Appropriate credits would be supplied if I knew who to credit. In any case, I thought that you might want to review this code, and use it with the code you wrote.

Code:
 alias fmtdur { 
  ; Usage: $fmtdur(secs [, format])  
  ; Formatting: [y year] [m month] [w week] [d day] [h hour] [n minute] [s second] [u units]  
  ; Using the same character consecutively will zeropad that unit to the given length (ie. n = 7, nnn = 007)  
  ; Doubling the u character will cause it to use the full format (ie. nu = 6mins, nuu = 6minutes)  
  ; Uppercase U characters will capitalize units. 
  var %fmt = $iif($2,$2,wu du hu nu su), %secs = $int($1), %count = $regex(fmtdur, %fmt, /(([^ymwdhns]*)(y+|m+|w+|d+|h+|n+|s+)([^ymwdhnsUu]*)([Uu]*))/g)  
  var %yrs, %mnths, %wks, %days, %hrs, %mins, %i = 1, %fmtchars, %unitchars, %durstr, %amount, %units 
  if (y isincs %fmt) { %yrs = $int($calc(%secs / 31557600)) | %secs = $calc(%secs % 31557600) }  
  if (m isincs %fmt) { %mnths = $int($calc(%secs / 2629800)) | %secs = $calc(%secs % 2629800) }  
  if (w isincs %fmt) { %wks = $int($calc(%secs / 604800)) | %secs = $calc(%secs % 604800) }  
  if (d isincs %fmt) { %days = $int($calc(%secs / 86400)) | %secs = $calc(%secs % 86400) }  
  if (h isincs %fmt) { %hrs = $int($calc(%secs / 3600)) | %secs = $calc(%secs % 3600) }  
  if (n isincs %fmt) { %mins = $int($calc(%secs / 60)) | %secs = $calc(%secs % 60) } 
  while %i <= $calc(%count * 5) { 
    %fmtchars = $regml(fmtdur, $calc(%i + 2))    
    %unitchars = $regml(fmtdur, $calc(%i + 4))    
    %amount = $charpad($replace($left(%fmtchars, 1),y,%yrs,m,%mnths,w,%wks,d,%days,h,%hrs,n,%mins,s,%secs), $len(%fmtchars), 0)    
    if (u isin %unitchars) { 
      if ($len(%unitchars) == 1) %units = $replacex($left(%fmtchars,1),y,yr,m,mth,w,wk,d,dy,h,hr,n,min,s,sec)      
      else %units = $replacex($left(%fmtchars,1),y,year,m,month,w,week,d,day,h,hour,n,minute,s,second)      
      if (%amount != 1) %units = $+(%units, s)      
      if (U isincs %unitchars) %units = $+($upper($left(%units,1)), $right(%units,-1))    
    } 
    else %units = $null    
    %durstr = $+($left(%durstr, -1), $regml(fmtdur, $calc(%i + 1)), %amount, $regml(fmtdur, $calc(%i + 3)), %units, x))    
    inc %i 5  
  } 
  return $left(%durstr, -1) 
} 
 

Re: Making $duration include months/years #126252 27/07/05 01:42 AM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Hm... so, add formatting options? I could do that. I'll have to think about how I want to do that and probably not do it until tomorrow or whatever... but would be useful before submitting it.

Any other thoughts?


Invision Support
#Invision on irc.irchighway.net
Re: Making $duration include months/years #126253 27/07/05 10:50 AM
Joined: Apr 2003
Posts: 701
K
Kelder Offline
Hoopy frood
Offline
Hoopy frood
K
Joined: Apr 2003
Posts: 701
Also check out my earlier post about date differences. Maybe it gives you some ideas...

Re: Making $duration include months/years #126254 27/07/05 01:37 PM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Ok, an update to improve the coding thanks to ideas from Kelder's script as well as some of my own. I also changed the variable names a bit to help prevent any conflicts with other scripts. And, it's been updated to work on mIRC 6.16. Apparently 6.16 doesn't have $year anymore. I had written this for 6.14 to begin with and didn't realize it wouldn't work on 6.16 because of the $year. Anyhow, it now works on 6.16.

Any other suggestions for improvement? I still will see about adding formatting options like mentioned. I'm having an issue with making the format work properly, though....

The problem is the if I do something like $datexpander(40wks 2days 3hrs,mmddhh) then the comma is removed, so I can't just use it as a token. Why is that? I obviously don't want to make people use something other than a comma... and I'd rather save code so that I don't have to check the last $chr(32) token in order to see if it's formatting information.

Btw, try it out with: //echo -a $datexpander($duration($ctime)) laugh

Code:
; *******************************************************************
; DateXpander Script
; by Riamus 2005
;
; Suggestions and ideas for improvement from mIRC.com's forum
;
; This script will take a standard $duration and make it include months and years
; based on the current date.
;
; For this script to be accurate, it is only meant to be used when the $duration is
; using today's date and counting backwards (such as an uptime $duration). It
; will still be really accurate (within 3 days) even if you use a $duration that isn't
; from the current date, but it won't be exact that way.
;
; Use: $DateXpander(value)
; "value" must be in the format of $duration
;
; For questions about this script, contact Riamus on IRC -- #oldgames on irc.undernet.org
; *******************************************************************

alias DateXpander {
  unset %dx-dateoutput

  if ($1- isalpha || $1- isnum) {
    echo -a Error.  Use the same format as in $chr(36) $+ duration.
    halt
  }

  set %dx_weeks $iif($gettok($1-,1,119) isnum,$gettok($1-,1,119),0)
  set %dx_days $iif($gettok($gettok($1-,1,100),-1,32) isnum,$gettok($gettok($1-,1,100),-1,32),0)
  set %dx_hours $iif($gettok($gettok($1-,1,104),-1,32) isnum,$gettok($gettok($1-,1,104),-1,32),0)
  set %dx_minutes $iif($gettok($gettok($1-,1,109),-1,32) isnum,$gettok($gettok($1-,1,109),-1,32),0)
  set %dx_seconds $iif(sec isin $gettok($1-,$gettok($1-,0,32),32),$gettok($gettok($1-,$gettok($1-,0,32),32),1,115),0)
  set %dx_totaldays $calc(%dx_weeks * 7 + %dx_days)

  set %dx_currentmonth $date(m)

  :monthstart
  if (%dx_currentmonth == 12 || %dx_currentmonth == 10 || %dx_currentmonth == 7 || %dx_currentmonth == 5) {
    set %dx_monthdays 30
  }
  elseif (%dx_currentmonth == 11 || %dx_currentmonth == 9 || %dx_currentmonth == 8 || %dx_currentmonth == 6 || %dx_currentmonth == 4 || %dx_currentmonth == 2 || %dx_currentmonth == 1) {
    set %dx_monthdays 31
  }
  elseif (%dx_currentmonth == 3 && $calc($date(yyyy) % 4) != 0) {
    set %dx_monthdays 28
  }
  elseif (%dx_currentmonth == 3 && $calc($date(yyyy) % 4) == 0) {
    set %dx_monthdays 29
  }
  if (%dx_totaldays >= %dx_monthdays) {
    inc %dx_months
    dec %dx_totaldays %dx_monthdays
    if (%dx_currentmonth != 1) {
      dec %dx_currentmonth
    }
    else { set %dx_currentmonth 12 }
    goto monthstart
  }

  set %dx_years $int($calc(%dx_months / 12))
  dec %dx_months $calc(%dx_years * 12)
  set %dx_weeks $int($calc(%dx_totaldays / 7))
  set %dx_totaldays $calc(%dx_totaldays - (%dx_weeks * 7))

  if (%dx_years > 1) { set %dx-dateoutput %dx-dateoutput %dx_years $+ _years }
  elseif (%dx_years == 1) { set %dx-dateoutput %dx-dateoutput %dx_years $+ _year }
  if (%dx_months > 1) { set %dx-dateoutput %dx-dateoutput %dx_months $+ _months }
  elseif (%dx_months == 1) { set %dx-dateoutput %dx-dateoutput %dx_months $+ _month }
  if (%dx_weeks > 1) { set %dx-dateoutput %dx-dateoutput %dx_weeks $+ _weeks }
  elseif (%dx_weeks == 1) { set %dx-dateoutput %dx-dateoutput %dx_weeks $+ _week }
  if (%dx_totaldays > 1) { set %dx-dateoutput %dx-dateoutput %dx_totaldays $+ _days }
  elseif (%dx_totaldays == 1) { set %dx-dateoutput %dx-dateoutput %dx_totaldays $+ _day }
  if (%dx_hours > 1) { set %dx-dateoutput %dx-dateoutput %dx_hours $+ _hours }
  elseif (%dx_hours == 1) { set %dx-dateoutput %dx-dateoutput %dx_hours $+ _hour }
  if (%dx_minutes > 1) { set %dx-dateoutput %dx-dateoutput %dx_minutes $+ _minutes }
  elseif (%dx_minutes == 1) { set %dx-dateoutput %dx-dateoutput %dx_minutes $+ _minute }
  if (%dx_seconds > 1) { set %dx-dateoutput %dx-dateoutput %dx_seconds $+ _seconds }
  elseif (%dx_seconds == 1) { set %dx-dateoutput %dx-dateoutput %dx_seconds $+ _second }

  unset %dx_*

  return $replace(%dx-dateoutput,$chr(32),$chr(44) $+ $chr(32),_,$chr(32))
}

Last edited by Riamus2; 27/07/05 01:58 PM.

Invision Support
#Invision on irc.irchighway.net
Re: Making $duration include months/years #126255 27/07/05 04:15 PM
Joined: Apr 2003
Posts: 701
K
Kelder Offline
Hoopy frood
Offline
Hoopy frood
K
Joined: Apr 2003
Posts: 701
Some coding suggestions:

- use /var instead of /set vor local variables, you can use short names too then
- goto is evil
- I'm a fan of regex, can't help it:

if (!$regex($1-,/^\s*(?:(\d+)wks?|())\s*(?:(\d+)days?|())\s*(?:(\d+)hrs?|())\s*(?:(\d+)mins?|())\s*(?:(\d+)secs?|()))) return
var %weeks = $regml(1), %days = $regml(2), %hours = $regml(3)
var %minutes = $regml(4), %seconds = $regml(5), %totaldays = $calc(%weeks * 7 + %days)

- how about
if ($istok(%currentmonth,4.6.9.11,46)) var %monthdays = 30
instead of 6 different tests?

- are you sure you need that _ to space conversion?

Re: Making $duration include months/years #126256 27/07/05 05:16 PM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Well, those could be used... yet, I have issues with them.

var vs set... The output changes if I replace all of the sets with vars (yes, I'm using the right format for var). Probably a reason for it, but it's not a big deal to use set. And, I use the longer variable names to make it understandable to others. I don't like reading people's scripts and trying to see what it is doing when all the variables are single or double letters... just my preference.

goto ... do you have another loop suggestion? It works... why not use it? It's true that I rarely use goto, but it seems to fit best here. I suppose I could use a while loop, but this just seems better in this case to me.

For the regex... I'm not too worried about using it. Once I really get the hang of it, I may start using regex, but I prefer not to use code that I don't really have a handle on. Makes it harder for me to mess with it later.

I did insert the $istok method as it probably is faster. Though, I had to change the order you suggested to:

$istok(4.6.9.11,%currentmonth,46)

As far as the _ to space conversion... I am not sure of a better way to stick in the commas. If I just have spaces, then replacing spaces with commas results in an output like

2, years, 1, months, 2, days

By using the _, I can easily insert commas without ending up having a comma at the end of the line, like:

2 years, 4 weeks, 1 day, 2 hours,


Invision Support
#Invision on irc.irchighway.net
Re: Making $duration include months/years #126257 27/07/05 08:57 PM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Any ideas on the , issue I mentioned above?

$datexpander(4wks 3days 2mins,wwdd)

If I echo the $1-, I get:

4wks 3days 2mins wwdd

(no comma).

I can make it work fine with other characters, but commas disappear. Is there some way to prevent that? I really don't want to have to code checks to find out of the last $chr(32) token is the formatting information if I don't have to.

Thanks.


Invision Support
#Invision on irc.irchighway.net
Re: Making $duration include months/years #126258 27/07/05 09:28 PM
Joined: Apr 2003
Posts: 701
K
Kelder Offline
Hoopy frood
Offline
Hoopy frood
K
Joined: Apr 2003
Posts: 701
You do know that in $datexpander(4wks 3days 2mins,wwdd)
$1 == 4wks 3days 2mins
and $2 = wwdd
right?

If there are commas between 4wks, 3days, 2 mins, then you'll have to check if $ [ $+ [ $0 ] ] contains a number or not...

ps: $duration can output just one of the intervals, $duration(3600) returns 1hr and not 1hr 0mins 0secs

Re: Making $duration include months/years #126259 28/07/05 12:52 PM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Ok, no... I didn't realize $2 would be the part after the comma. I had assumed it used the standard space tokens. Thanks.

As for your PS, that isn't an issue. The script doesn't need all the parts to be there. It will also only output the items that have a value.


Invision Support
#Invision on irc.irchighway.net
Re: Making $duration include months/years #126260 29/07/05 10:57 AM
Joined: Sep 2003
Posts: 4,230
D
DaveC Offline
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
I was sitting at home last night with nothing to do so thought id have a go at one myself, man was that a mistake, I almost gave up twice. I thought it would be simple, just a matter of subtracting the first date from the second, and it is but theres alot of little fiddly bits that i didnt take into account, some not with the calculation itself but with $ctime and how it replies with a count of seconds between your localtime and 1970-01-01 00:00:00 GMT time, im at +12gmt so i cant even get a value on that date/time first i get is 1970-01-01 12:00:00, this was a second problem I encountered, and nearly tossed it for it. Anyway enough complaining heres what I came up with.

[code]
;Duration.From.To.Format
; * Pass it any two dates that $ctime can return values for (1970-01-01 00:00:00 +-12 hours onward to sometime)
; * and it returns back the yrs,mths,wks,days,hrs,mins,secs from one to the other. A few output format options also see below.
;
;usage $Duration.From.To.Format($1,$2,$3)
; $1 = $date $time
; $2 = $date $time
; $3 = formating (as follows)
; e=short extentions yrs,mths,wks,days,hrs,mins,secs (default)
; E=long extentions years,months,weeks,days,hours,minutes,seconds (overrides e)
; a=all fields
; A=all fields no extentions (overrides e & E & a)
; z=zeropad fields years(4) Months(2) Weeks(1) Days(1) Hours(2) Minutes(2) Seconds(2)
;
alias Duration.From.To.Format {
var %c1 = $ctime($1), %c2 = $ctime($2)
if ((%c1 == $null) || (%c2 == $null)) { RETURN }
if (%c1 < %c2) { var -s %temp = %c1, %c1 = %c2, %c2 = %temp }
var %y1 = $date(%c1,yyyy), %m1 = $date(%c1,mm), %d1 = $date(%c1,dd), %t1 = $calc($time(%c1,HH) * 3600 + $time(%c1,nn) * 60 + $time(%c1,ss))
var %y2 = $date(%c2,yyyy), %m2 = $date(%c2,mm), %d2 = $date(%c2,dd), %t2 = $calc($time(%c2,HH) * 3600 + $time(%c2,nn) * 60 + $time(%c2,ss))
if (%t1 < %t2) { inc %t1 86400 | dec %d1 }
if (%d1 < %d2) { inc %d1 $gettok(31 $iif(!$calc(%y1 % 4),29,28) 31 30 31 30 31 31 30 31 30 31,%m2,32) | dec %m1 }
if (%m1 < %m2) { inc %m1 12 | dec %y1 }
var %y0 = $calc(%y1 - %y2), %m0 = $calc(%m1 - %m2), %d0 = $calc(%d1 - %d2), %t0 = $calc(%t1 - %t2), %w0 = $int($calc(%d0 / 7))
var %d0 = $calc(%d0 % 7), %h0 = $int($calc(%t0 / 3600)), %n0 = $int($calc((%t0 % 3600) / 60)), %s0 = $calc(%t0 % 60)
;
if ((A isincs $3) && (z isin $3)) { RETURN $right($+(0000,%y0),4) $right($+(00,%m0),2) %w0 %d0 $right($+(00,%h0),2) $right($+(00,%n0),2) $right($+(00,%s0),2) }
if ((A isincs $3)) { RETURN %y0 %m0 %m0 %w0 %d0 %h0 %n0 %s0 }
if ((a isincs $3) && (E isincs $3) && (z isin $3)) { RETURN $+($right($+(0000,%y0),4),$iif(%y0 == 1,year,years)) $+($right($+(00,%m0),2),$iif(%m0 == 1,month,months)) $+(%w0,$iif(%w0 == 1,week,weeks)) $+(%d0,$iif(%d0 == 1,day,days)) $+($right($+(00,%h0),2),$iif(%h0 == 1,hour,hours)) $+($right($+(00,%n0),2),$iif(%n0 == 1,minute,minutes)) $+($right($+(00,%s0),2),$iif(%s0 == 1,second,seconds)) }
if ((a isincs $3) && (E isincs $3)) { RETURN $+(%y0,$iif(%y0 == 1,year,years)) $+(%m0,$iif(%m0 == 1,month,months)) $+(%w0,$iif(%w0 == 1,week,weeks)) $+(%d0,$iif(%d0 == 1,day,days)) $+(%h0,$iif(%h0 == 1,hour,hours)) $+(%n0,$iif(%n0 == 1,minute,minutes)) $+(%s0,$iif(%s0 == 1,second,seconds)) }
if ((a isincs $3) && (z isin $3)) { RETURN $+($right($+(0000,%y0),4),$iif(%y0 == 1,yr,yrs)) $+($right($+(00,%m0),2),$iif(%m0 == 1,mth,mths)) $+(%w0,$iif(%w0 == 1,wk,wks)) $+(%d0,$iif(%d0 == 1,day,days)) $+($right($+(00,%h0),2),$iif(%h0 == 1,hr,hrs)) $+($right($+(00,%n0),2),$iif(%n0 == 1,min,mins)) $+($right($+(00,%s0),2),$iif(%s0 == 1,sec,secs)) }
if ((a isincs $3)) { RETURN $+(%y0,$iif(%y0 == 1,yr,yrs)) $+(%m0,$iif(%m0 == 1,mth,mths)) $+(%w0,$iif(%w0 == 1,wk,wks)) $+(%d0,$iif(%d0 == 1,day,days)) $+(%h0,$iif(%h0 == 1,hr,hrs)) $+(%n0,$iif(%n0 == 1,min,mins)) $+(%s0,$iif(%s0 == 1,sec,secs)) }
if ((E isincs $3) && (z isin $3)) { RETURN $iif(%y0,$+($right($+(0000,%y0),4),$iif(%y0 == 1,year,years))) $iif(%m0,$+($right($+(00,%m0),2),$iif(%m0 == 1,month,months))) $iif(%w0,$+(%w0,$iif(%w0 == 1,week,weeks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+($right($+(00,%h0),2),$iif(%h0 == 1,hour,hours))) $iif(%n0,$+($right($+(00,%n0),2),$iif(%n0 == 1,minute,minutes))) $iif(%s0,$+($right($+(00,%s0),2),$iif(%s0 == 1,second,seconds))) }
if ((E isincs $3)) { RETURN $iif(%y0,$+(%y0,$iif(%y0 == 1,year,years))) $iif(%m0,$+(%m0,$iif(%m0 == 1,month,months))) $iif(%w0,$+(%w0,$iif(%w0 == 1,week,weeks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+(%h0,$iif(%h0 == 1,hour,hours))) $iif(%n0,$+(%n0,$iif(%n0 == 1,minute,minutes))) $iif(%s0,$+(%s0,$iif(%s0 == 1,second,seconds))) }
if ((z isin $3)) { RETURN $iif(%y0,$+($right($+(0000,%y0),4),$iif(%y0 == 1,yr,yrs))) $iif(%m0,$+($right($+(00,%m0),2),$iif(%m0 == 1,mth,mths))) $iif(%w0,$+(%w0,$iif(%w0 == 1,wk,wks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+($right($+(00,%h0),2),$iif(%h0 == 1,hr,hrs))) $iif(%n0,$+($right($+(00,%n0),2),$iif(%n0 == 1,min,mins))) $iif(%s0,$+($right($+(00,%s0),2),$iif(%s0 == 1,sec,secs))) }
if (($true)) { RETURN $iif(%y0,$+(%y0,$iif(%y0 == 1,yr,yrs))) $iif(%m0,$+(%m0,$iif(%m0 == 1,mth,mths))) $iif(%w0,$+(%w0,$iif(%w0 == 1,wk,wks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+(%h0,$iif(%h0 == 1,hr,hrs))) $iif(%n0,$+(%n0,$iif(%n0 == 1,min,mins))) $iif(%s0,$+(%s0,$iif(%s0 == 1,sec,secs))) }
}
[code]

* wouldnt mind someone running it through the grinder, seeing if you can break it, Im not overly convinced i got the bit when you have a bigger day count to take off a smaller one, like if u have a time of 8:12 and 4:16 to take off it, you just make it 7:72 - 4:16 = 3:56, but when its a day count you cant just add 28,29,30,31 whcih one is it?!?!?! I think i got it right but then again.
This line is where i likely have a fault.
if (%d1 < %d2) { inc %d1 $gettok(31 $iif(!$calc(%y1 % 4),29,28) 31 30 31 30 31 31 30 31 30 31,%m2,32) | dec %m1 }
It might need to be
if (%d1 < %d2) { inc %d1 $gettok(31 $iif(!$calc(%y2 % 4),29,28) 31 30 31 30 31 31 30 31 30 31,%m2,32) | dec %m1 }
* its designed to add a months days onto the first day count so the second day count can be removed from it, and it then adjusts the month count down by one.

Re: Making $duration include months/years #126261 29/07/05 12:27 PM
Joined: Apr 2003
Posts: 701
K
Kelder Offline
Hoopy frood
Offline
Hoopy frood
K
Joined: Apr 2003
Posts: 701
ok, apparently this coding is fun grin, so I augmented mine to support weeks and parameters, and fixed some bugs. For those wondering, yes I love regex smirk

Code:
alias datediff {
  ; calculate difference between date 1 and date 2, in years,months,(weeks),days,hours,minutes,seconds
  ; usage $datediff(dd/mm/yyyy HH:nn:ss, dd/mm/yyyy HH:nn:ss)
  ; meaning $datediff($date $time, $date $time)
  ; example:  //echo -a $datediff(3/5/2005 20:00:10, 5/10/2000 12:15:20)
  ; ** IMPORTANT: $date uses dd/mm/yyyy, if you want to input mm/dd/yyyy style, 
  ; **   add a third parameter 'u'
  ; other parameters
  ;  w = use weeks
  ;  a = display all fields, also 0 values
  ;  s = short duration identifiers
  ;  n = no spaces between numbers and durations
  ;  d = only numbers, no durations (use 'a' too or you won't have a clue what it means ;)
  ;  z = zeropad fields years(4) months(2) weeks(1) days(1) hours(2) minutes(2) seconds(2)
  ; example:  //echo -a $datediff(1/5/2005 11:15:22pm, 1/8/2005 12:15:22P.M., uws)
  ; hh:nn:ss am/pm is supported (only now I realize how strange it actually is)
  ; my reference: http://www.worldtimezone.com/wtz-names/wtz-am-pm.html

  var %1 = $1, %2 = $2, %switched = $false
  :dateswitch
  if ($regex(%2,/^0*(\d+)\D0*(\d+)\D(\d+)\D0*(\d+)\D0*(\d+)\D0*(\d+)(?:\D?([ap]\.?m\.?|noon|midday|midnight))?$/i)) {
    var %d1 = $regml($iif(u isin $3,2,1)), %m1 = $regml($iif(u isin $3,1,2))
    var %h1 = $regml(4), %n1 = $regml(5), %s1 = $regml(6), %y1 = $regml(3)
    if ((%h1 == 12) &amp;&amp; (($regml(7) == am) || ($v1 == midnight))) var %h1 = 0
    elseif ((%h1 isnum 1-11) &amp;&amp; ($regml(7) == pm)) inc %h1 12
  }
  else return Date 1 in incorrect format
  if ($regex(%1,/^0*(\d+)\D0*(\d+)\D(\d+)\D0*(\d+)\D0*(\d+)\D0*(\d+)(?:\D?([ap]\.?m\.?|noon|midday|midnight))?$/i)) {
    var %d2 = $regml($iif(u isin $3,2,1)), %m2 = $regml($iif(u isin $3,1,2))
    var %h2 = $regml(4), %n2 = $regml(5), %s2 = $regml(6), %y2 = $regml(3)
    if ((%h2 == 12) &amp;&amp; (($regml(7) == am) || ($v1 == midnight))) var %h2 = 0
    elseif ((%h2 isnum 1-11) &amp;&amp; ($regml(7) == pm)) inc %h2 12
  }
  else return Date 2 in incorrect format
  if ((%m1 !isnum 1-12) || (%d1 !isnum 1-31) || (%h1 !isnum 0-23) || (%m1 !isnum 0-59) $&amp;
    || (%s1 !isnum 0-59)) return Date 1 invalid
  if ((%m2 !isnum 1-12) || (%d2 !isnum 1-31) || (%h2 !isnum 0-23) || (%m2 !isnum 0-59) $&amp;
    || (%s2 !isnum 0-59)) return Date 2 invalid
  var %s = %s1 - %s2 | if (%s &lt; 0) var %s = %s + 60, %n1 = %n1 - 1
  var %n = %n1 - %n2 | if (%n &lt; 0) var %n = %n + 60, %h1 = %h1 - 1
  var %h = %h1 - %h2 | if (%h &lt; 0) var %h = %h + 24, %d1 = %d1 - 1
  var %d = %d1 - %d2
  if (%d &lt; 0) var %d = %d + $gettok(31 $iif((!$calc(%y1 % 400)) || (($calc(%y1 % 100)) $&amp;
    &amp;&amp; (!$calc(%y1 % 4))),29,28) 31 30 31 30 31 31 30 31 30 31,%m1,32), %m1 = %m1 - 1
  var %m = %m1 - %m2, %y = %y1 - %y2, %w
  if (%m &lt; 0) var %m = %m + 12, %y = %y - 1
  if (%y &lt; 0) { if (%switched) return ERROR | var %1 = $2, %2 = $1, %switched = $true | goto dateswitch }

  if ( w  isin $3) var %w = $int($calc(%d / 7)) weeks, %d = $calc(%d - 7 * %w)
  if ( z  isin $3) var %y = $base(%y,10,10,4), %m = $base(%m,10,10,2), %d = $base(%d,10,10,2), $&amp;
    %h = $base(%h,10,10,2), %n = $base(%n,10,10,2), %s = $base(%s,10,10,2)
  var %res = %y years %m months %w %d days %h hours %n minutes %s seconds
  if ((a !isin $3) &amp;&amp; ( $regsub(%res,/(?&lt;!\d)0 \w++/g,,%res) )) { }
  if ( s  isin $3) { var %res = $replace(%res,year,yr,month,mth,week,wk,hour,hr,minute,min,second,sec) }
  $null($regsub(%res,/(?&lt;!\d)(1 \w+)s(?!\w)/g,\1,%res))
  if ((n  isin $3) &amp;&amp; ( $regsub(%res,/(?&lt;=\d)\s+(?=\w)/g,,%res) )) { }
  if ((d  isin $3) &amp;&amp; ( $regsub(%res,/\w/g,,%res) )) { }
  return %res
}

Here's what I use as testing between your code and mine
Code:
//var %d1 = 1/1/2007 14:00:00, %d2 = 2/2/2006 13:01:01 | echo -s dftf____ $Duration.From.To.Format(%d1, %d2) | echo -s datediff $datediff(%d1,%d2,nws)

Yes, it gives different output, I think it's not my problem but yours :tongue: (change both a year to the future too)
Also, 2000 is a leap year, you didn't consider that. I did steal your $gettok concept tho smile

Re: Making $duration include months/years #126262 29/07/05 12:54 PM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Mine isn't designed to tell you the difference between two dates. If you already have the $duration of that, then it will work correctly. Future dates don't matter for this script because it is using $duration which doesn't consider dates. Note also that as the header says, this is meant for $durations that are between the current date and going backwards as for use with $uptime. In that format, it will be completely accurate. If used in another way, it will be anywhere from 0 days to 3 days off. It should never be more than 3 days off (unless you go back far enough that you're back to the point in time where 12 days were added to the calendar).

Why 3 days? Because it checks months in order, it could be off because it thinks that it's one month when it's really another month. Months are 28-31 days. So, it could be off by up to 3 days because of that difference. It could also be right on the mark even if it's using another date than today's depending on the length of the $duration and the date it starts at.

I could easily set it up to allow a user to input a starting date (by starting, I mean the most future date as this is really meant to go backwards) and then it would be accurate all the time if the user enters the correct starting date. Whether or not I will do that, I am not sure.

And, yes... I did consider leap years. Check the 28 vs 29 section of the code.

I may have an update for my script done today with formatting and the $istok idea (that's already coded, but I don't see a need to paste that small update here).


Invision Support
#Invision on irc.irchighway.net
Re: Making $duration include months/years #126263 29/07/05 02:56 PM
Joined: Apr 2003
Posts: 701
K
Kelder Offline
Hoopy frood
Offline
Hoopy frood
K
Joined: Apr 2003
Posts: 701
It was a reply to DaveC, so those comments (about leap years etc) weren't directed at you smile

But I was bored (no, I didn't like what I should be doing) so I wrote something more appropriate to your problem:

You'll need the $datediff function above too...
(Sorry about the whole lot of code)
Code:
; Return duration in years/months/days starting from a specific date and a duration in
; (one, more or all of) years/months/weeks/days/hours/minutes/seconds
; usage: $datediff3(25/12/2002 10:35:00,1yr 252wks 15mths 60days 25hrs 61secs,past,nsw)
; use past for having a duration to something that's in the past and future for something in the future
; use now as date for using the current date.
; nsw -&gt; see switches of $datediff
alias datediff3 return $datediff($1,$datediff2($1,$2,$3,$4),$4)

; Return the date something happened or will happen based on start date and duration

; usage: $datediff3(25/12/2002 10:35:00,1yr 252wks 15mths 60days 25hrs 61secs,past)
; use past for having a duration to something that's in the past and future for something in the future
; use now as date for using the current date.
; use u as 4th parameter only for mm/dd/yyy hh:nn:ss style dates
alias datediff2 {
  var %1 = $iif($1 == now,$date(dd/mm/yyyy hh:nn:ss),$1) , %2 = $$2
  if ($regex(%1,/^0*(\d+)\D0*(\d+)\D(\d+)\D0*(\d+)\D0*(\d+)\D0*(\d+)(?:\D?([ap]\.?m\.?|noon|midday|midnight))?$/i)) {
    var %d1 = $regml($iif(u isin $4,2,1)), %m1 = $regml($iif(u isin $4,1,2))
    var %h1 = $regml(4), %n1 = $regml(5), %s1 = $regml(6), %y1 = $regml(3)
    if ((%h1 == 12) &amp;&amp; (($regml(7) == am) || ($v1 == midnight))) var %h1 = 0
    elseif ((%h1 isnum 1-11) &amp;&amp; ($regml(7) == pm)) inc %h1 12
  }
  if ((%m1 !isnum 1-12) || (%d1 !isnum 1-31) || (%h1 !isnum 0-23) || (%m1 !isnum 0-59) || (%s1 !isnum 0-59)) return Date invalid


  if ($regex(%2,/^(?:(\d+) *y\w* |())(?:(\d+) *mo?n?ths? |())(?:(\d+) *w\w* |())(?:(\d+) *d\w* |()) $+ $&amp;
    (?:(\d+) *h\w* |())(?:(\d+) *mi\w* |())(?:(\d+) *s\w*|()) *$/i)) {
    var %y = $calc($regml(1)), %m = $calc($regml(2)), %d = $calc(7 * $calc($regml(3)) + $calc($regml(4)))
    var %h = $calc($regml(5)), %n = $calc($regml(6)), %s = $calc($regml(7))
  }
  else return invalid duration given...

  if ($3 == future) {
    var %s2 = %s1 + %s
    while (%s2 &gt; 60) var %s2 = %s2 - 60, %n = %n + 1
    var %n2 = %n1 + %n
    while (%n2 &gt; 60) var %n2 = %n2 - 60, %h = %h + 1
    var %h2 = %h1 + %h
    while (%h2 &gt; 24) var %h2 = %h2 - 24, %d = %d + 1
    var %m2 = %m1 + %m
    while (%m2 &gt; 12) var %m2 = %m2 - 12, %y = %y + 1
    var %y2 = %y1 + %y, %d2 = %d1 + %d
    while (%d2 &gt; $gettok(31 $iif((!$calc(%y2 % 400)) || (($calc(%y2 % 100)) &amp;&amp; (!$calc(%y2 % 4))),29,28) 31 30 31 30 31 31 30 31 30 31,%m2,32)) {
      var %d2 = %d2 - $v2, %m2 = %m2 + 1
      if (%m2 &gt; 12) var %m2 = %m2 - 12, %y2 = %y2 + 1
    }
  }
  elseif ($3 == past) {
    var %s2 = %s1 - %s
    while (%s2 &lt; 0) var %s2 = %s2 + 60, %n = %n - 1
    var %n2 = %n1 - %n
    while (%n2 &lt; 0) var %n2 = %n2 + 60, %h = %h - 1
    var %h2 = %h1 - %h
    while (%h2 &lt; 0) var %h2 = %h2 + 24, %d = %d - 1
    var %m2 = %m1 - %m
    while (%m2 &lt; 1) var %m2 = %m2 + 12, %y = %y - 1
    var %y2 = %y1 - %y, %d2 = %d1 - %d
    while (%d2 &lt; 1) {
      var %d2 = %d2 + $gettok(31 $iif((!$calc(%y2 % 400)) || (($calc(%y2 % 100)) &amp;&amp; (!$calc(%y2 % 4))),29,28) 31 30 31 30 31 31 30 31 30 31,%m2,32)
      var %m2 = %m2 - 1 | if (%m2 &lt; 1) var %m2 = %m2 + 12, %y2 = %y2 - 1
    }
  }
  else return uhm, you want the third parameter to be future or past...
  if (u isin $4) return $+($base(%m2,10,10,2),/,$base(%d2,10,10,2),/,$base(%y2,10,10,4) $base(%h2,10,10,2),:,$base(%n2,10,10,2),:,$base(%s2,10,10,2))
  return $+($base(%d2,10,10,2),/,$base(%m2,10,10,2),/,$base(%y2,10,10,4) $base(%h2,10,10,2),:,$base(%n2,10,10,2),:,$base(%s2,10,10,2))
}


This should give what you want, probably in a more elaborate (read: slower) way than yours. It should never be off, unless you just slam in the wrong start date smile
//echo -s $datediff3(1/1/2005 12:5:5,252wks 700days 80mins 59secs, past,snw)

Re: Making $duration include months/years #126264 29/07/05 03:04 PM
Joined: Sep 2003
Posts: 4,230
D
DaveC Offline
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
Thats some intense regex code dude!

[qoute]Here's what I use as testing between your code and mine
Code:
//var %d1 = 1/1/2007 14:00:00, %d2 = 2/2/2006 13:01:01 | echo -s dftf____ $Duration.From.To.Format(%d1, %d2) | echo -s datediff $datediff(%d1,%d2,nws)

Yes, it gives different output, I think it's not my problem but yours :tongue: (change both a year to the future too)
Also, 2000 is a leap year, you didn't consider that. I did steal your $gettok concept tho smile [/quote]

On the 2000 being a leap year. I dont really get you. Mine does have it as a leap year. I didnt worry about the every 100 not a leap but every 400 is, since 2000 is and mine was limited to dates definable under $ctime, its actually only limited to that becuase i was to lazy to errorcheck the inputs.


However it appears its yours and mine that are incorrect, while either of those results can be deemed correct, they are only so by chance.
dftf____ 10mths 3wks 6days 58mins 59secs mine advances 3wks & 6 days (27 days) from 2/2/2006 to 1/3/2006 then advances 10 months to 1/1/2007
datediff 10mths 4wks 2days 58mins 59secs yours advances 10 months from 2/2/2006 to 2/12/2006 then 4wks & 2 days (30 days) to 1/1/2007

Yours begins to fail on closer values

//var %d1 = 1/3/2006 00:00:00, %d2 = 2/2/2006 00:00:00 | echo -s dftf____ $Duration.From.To.Format(%d1, %d2) | echo -s datediff $datediff(%d1,%d2,nws)
dftf____ 3wks 6days
datediff 4wks 2days

Few to many for FEB frown

While mine appeared to maintain a valid number of days, on closer inspection, the flow was not correct, such as results like this.
4mths
3mths 3wks 6days, this was a valid value but used a system that did not flow with surounding dates
3mths 4wks,
3mths 3wks 6days

Anyway
heres mine corrected
[code]
;Duration.From.To.Format
; * Pass it any two dates that $ctime can return values for (1970-01-01 00:00:00 +-12 hours onward to sometime)
; * and it returns back the yrs,mths,wks,days,hrs,mins,secs from one to the other. A few output format options also see below.
;
;usage $Duration.From.To.Format($1,$2,$3)
; $1 = $date $time
; $2 = $date $time
; $3 = formating (as follows)
; e=short extentions yrs,mths,wks,days,hrs,mins,secs (default)
; E=long extentions years,months,weeks,days,hours,minutes,seconds (overrides e)
; a=all fields
; A=all fields no extentions (overrides e & E & a)
; z=zeropad fields years(4) Months(2) Weeks(1) Days(1) Hours(2) Minutes(2) Seconds(2)
;
alias Duration.From.To.Format {
var %c1 = $ctime($1), %c2 = $ctime($2)
if ((%c1 == $null) || (%c2 == $null)) { RETURN }
if (%c1 < %c2) { var %temp = %c1, %c1 = %c2, %c2 = %temp }
var %y1 = $date(%c1,yyyy), %m1 = $date(%c1,mm), %d1 = $date(%c1,dd), %t1 = $calc($time(%c1,HH) * 3600 + $time(%c1,nn) * 60 + $time(%c1,ss))
var %y2 = $date(%c2,yyyy), %m2 = $date(%c2,mm), %d2 = $date(%c2,dd), %t2 = $calc($time(%c2,HH) * 3600 + $time(%c2,nn) * 60 + $time(%c2,ss))
if (%t1 < %t2) { inc %t1 86400 | dec %d1 }
if (%d1 < %d2) { inc %d1 $gettok(31 31 $iif(!$calc(%y1 % 4),29,28) 31 30 31 30 31 31 30 31 30,%m1,32) | dec %m1 }
if (%m1 < %m2) { inc %m1 12 | dec %y1 }
var %y0 = $calc(%y1 - %y2), %m0 = $calc(%m1 - %m2), %d0 = $calc(%d1 - %d2), %t0 = $calc(%t1 - %t2), %w0 = $int($calc(%d0 / 7))
var %d0 = $calc(%d0 % 7), %h0 = $int($calc(%t0 / 3600)), %n0 = $int($calc((%t0 % 3600) / 60)), %s0 = $calc(%t0 % 60)
;
if ((A isincs $3) && (z isin $3)) { RETURN $right($+(0000,%y0),4) $right($+(00,%m0),2) %w0 %d0 $right($+(00,%h0),2) $right($+(00,%n0),2) $right($+(00,%s0),2) }
if ((A isincs $3)) { RETURN %y0 %m0 %m0 %w0 %d0 %h0 %n0 %s0 }
if ((a isincs $3) && (E isincs $3) && (z isin $3)) { RETURN $+($right($+(0000,%y0),4),$iif(%y0 == 1,year,years)) $+($right($+(00,%m0),2),$iif(%m0 == 1,month,months)) $+(%w0,$iif(%w0 == 1,week,weeks)) $+(%d0,$iif(%d0 == 1,day,days)) $+($right($+(00,%h0),2),$iif(%h0 == 1,hour,hours)) $+($right($+(00,%n0),2),$iif(%n0 == 1,minute,minutes)) $+($right($+(00,%s0),2),$iif(%s0 == 1,second,seconds)) }
if ((a isincs $3) && (E isincs $3)) { RETURN $+(%y0,$iif(%y0 == 1,year,years)) $+(%m0,$iif(%m0 == 1,month,months)) $+(%w0,$iif(%w0 == 1,week,weeks)) $+(%d0,$iif(%d0 == 1,day,days)) $+(%h0,$iif(%h0 == 1,hour,hours)) $+(%n0,$iif(%n0 == 1,minute,minutes)) $+(%s0,$iif(%s0 == 1,second,seconds)) }
if ((a isincs $3) && (z isin $3)) { RETURN $+($right($+(0000,%y0),4),$iif(%y0 == 1,yr,yrs)) $+($right($+(00,%m0),2),$iif(%m0 == 1,mth,mths)) $+(%w0,$iif(%w0 == 1,wk,wks)) $+(%d0,$iif(%d0 == 1,day,days)) $+($right($+(00,%h0),2),$iif(%h0 == 1,hr,hrs)) $+($right($+(00,%n0),2),$iif(%n0 == 1,min,mins)) $+($right($+(00,%s0),2),$iif(%s0 == 1,sec,secs)) }
if ((a isincs $3)) { RETURN $+(%y0,$iif(%y0 == 1,yr,yrs)) $+(%m0,$iif(%m0 == 1,mth,mths)) $+(%w0,$iif(%w0 == 1,wk,wks)) $+(%d0,$iif(%d0 == 1,day,days)) $+(%h0,$iif(%h0 == 1,hr,hrs)) $+(%n0,$iif(%n0 == 1,min,mins)) $+(%s0,$iif(%s0 == 1,sec,secs)) }
if ((E isincs $3) && (z isin $3)) { RETURN $iif(%y0,$+($right($+(0000,%y0),4),$iif(%y0 == 1,year,years))) $iif(%m0,$+($right($+(00,%m0),2),$iif(%m0 == 1,month,months))) $iif(%w0,$+(%w0,$iif(%w0 == 1,week,weeks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+($right($+(00,%h0),2),$iif(%h0 == 1,hour,hours))) $iif(%n0,$+($right($+(00,%n0),2),$iif(%n0 == 1,minute,minutes))) $iif(%s0,$+($right($+(00,%s0),2),$iif(%s0 == 1,second,seconds))) }
if ((E isincs $3)) { RETURN $iif(%y0,$+(%y0,$iif(%y0 == 1,year,years))) $iif(%m0,$+(%m0,$iif(%m0 == 1,month,months))) $iif(%w0,$+(%w0,$iif(%w0 == 1,week,weeks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+(%h0,$iif(%h0 == 1,hour,hours))) $iif(%n0,$+(%n0,$iif(%n0 == 1,minute,minutes))) $iif(%s0,$+(%s0,$iif(%s0 == 1,second,seconds))) }
if ((z isin $3)) { RETURN $iif(%y0,$+($right($+(0000,%y0),4),$iif(%y0 == 1,yr,yrs))) $iif(%m0,$+($right($+(00,%m0),2),$iif(%m0 == 1,mth,mths))) $iif(%w0,$+(%w0,$iif(%w0 == 1,wk,wks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+($right($+(00,%h0),2),$iif(%h0 == 1,hr,hrs))) $iif(%n0,$+($right($+(00,%n0),2),$iif(%n0 == 1,min,mins))) $iif(%s0,$+($right($+(00,%s0),2),$iif(%s0 == 1,sec,secs))) }
if (($true)) { RETURN $iif(%y0,$+(%y0,$iif(%y0 == 1,yr,yrs))) $iif(%m0,$+(%m0,$iif(%m0 == 1,mth,mths))) $iif(%w0,$+(%w0,$iif(%w0 == 1,wk,wks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+(%h0,$iif(%h0 == 1,hr,hrs))) $iif(%n0,$+(%n0,$iif(%n0 == 1,min,mins))) $iif(%s0,$+(%s0,$iif(%s0 == 1,sec,secs))) }
}
[code]


* yours needs the same patch applied
if (%d < 0) var %d = %d + $gettok(31 $iif((!$calc(%y1 % 400)) || (($calc(%y1 % 100)) && (!$calc(%y1 % 4))),29,28) 31 30 31 30 31 31 30 31 30 31,%m1,32), %m1 = %m1 - 1
must be replaced with
if (%d < 0) var %d = %d + $gettok(31 31 $iif((!$calc(%y1 % 400)) || (($calc(%y1 % 100)) && (!$calc(%y1 % 4))),29,28) 31 30 31 30 31 31 30 31 30,%m1,32), %m1 = %m1 - 1

The reasoning for this, i really had to sit down and work out on a bit of paper.
Say you have 2/1/2005 and the 1/4/2005 (d/m/y), you cant be taking 2 from 1 you get -1 so you must add a months days however its not the 4th month you add but the month before becuase your going to take that month off the date. Making you now doing the dates 2/1/2005 and 32/3/2005, which breaks to 30days one month.

I have run both yours and mine, and they follow the flow perfectly with this adjustment.
4mths
3mths 4wks 1day
3mths 4wks,
3mths 3wks 6days
etc

Re: Making $duration include months/years #126265 29/07/05 03:12 PM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Heh, Kelder... I thought both those script posts were from you. smile

Nice datediff scripts, btw.


Invision Support
#Invision on irc.irchighway.net
Re: Making $duration include months/years #126266 29/07/05 05:37 PM
Joined: Apr 2003
Posts: 701
K
Kelder Offline
Hoopy frood
Offline
Hoopy frood
K
Joined: Apr 2003
Posts: 701
Heh, you're right again, thanks for the fix! Since that code is in there 3 times and needs to be changed only 2 times, it's still nearly fried my brains smile

I did consider wether I'd add days first or months first, I knew there would be differences, but ofcourse I forgot that when I was comparing our scripts crazy

About the leap year stuff: I just looked at the tests and missed all required tests. Well, I actually looked at your script and wondered why my leap day test was 5 times longer smile I didn't consider then that it doesn't matter for your script since $ctime can't reach 1900 or 2100 anyways crazy

I found some more bugs too, and this time they're in my script frown frown Boundary problems where a time would be like 12:00:60 and such. And a regex problem where anything lacking seconds wouldn't be matched.

Final version, I could make the normal date format regex more allowing for missing hour, but letters are beginning to dance before my eyes...
(lotsa code, again frown )
Code:
; Return duration in years/months/days starting from a specific date and a duration in
; (one, more or all of) years/months/weeks/days/hours/minutes/seconds
; usage: $datediff3(25/12/2002 10:35:00,1yr 252wks 15mths 60days 25hrs 61secs,past,nsw)
; use past for having a duration to something that's in the past and future for something in the future
; use now as date for using the current date.
; nsw -&gt; see switches of $datediff
alias datediff3 return $datediff($1,$datediff2($1,$2,$3,$4),$4)

; Return the date something happened or will happen based on start date and duration

; usage: $datediff3(25/12/2002 10:35:00,1yr 252wks 15mths 60days 25hrs 61secs,past)
; use past for having a duration to something that's in the past and future for something in the future
; use now as date for using the current date.
; use u as 4th parameter only for mm/dd/yyy hh:nn:ss style dates
alias datediff2 {
  var %1 = $iif($1 == now,$date(dd/mm/yyyy hh:nn:ss),$1) , %2 = $$2
  if ($regex(%1,/^0*(\d+)\D0*(\d+)\D(\d+)\D0*(\d+)\D0*(\d+)\D0*(\d+)(?:\D?([ap]\.?m\.?|noon|midday|midnight))?$/i)) {
    var %d1 = $regml($iif(u isin $4,2,1)), %m1 = $regml($iif(u isin $4,1,2))
    var %h1 = $regml(4), %n1 = $regml(5), %s1 = $regml(6), %y1 = $regml(3)
    if ((%h1 == 12) &amp;&amp; (($regml(7) == am) || ($v1 == midnight))) var %h1 = 0
    elseif ((%h1 isnum 1-11) &amp;&amp; ($regml(7) == pm)) inc %h1 12
  }
  if ((%m1 !isnum 1-12) || (%d1 !isnum 1-31) || (%h1 !isnum 0-23) || (%m1 !isnum 0-59) || (%s1 !isnum 0-59)) return Date invalid


  if ($regex(%2,/^(?:(\d+) *y\w* *|())(?:(\d+) *mo?n?ths? *|())(?:(\d+) *w\w* *|())(?:(\d+) *d\w* *|()) $+ $&amp;
    (?:(\d+) *h\w* *|())(?:(\d+) *mi\w* *|())(?:(\d+) *s\w*|()) *$/i)) {
    var %y = $calc($regml(1)), %m = $calc($regml(2)), %d = $calc(7 * $calc($regml(3)) + $calc($regml(4)))
    var %h = $calc($regml(5)), %n = $calc($regml(6)), %s = $calc($regml(7))
  }
  else return invalid duration given...

  if ($3 == future) {
    var %s2 = %s1 + %s
    while (%s2 &gt; 59) var %s2 = %s2 - 60, %n = %n + 1
    var %n2 = %n1 + %n
    while (%n2 &gt; 59) var %n2 = %n2 - 60, %h = %h + 1
    var %h2 = %h1 + %h
    while (%h2 &gt; 23) var %h2 = %h2 - 24, %d = %d + 1
    var %m2 = %m1 + %m
    while (%m2 &gt; 12) var %m2 = %m2 - 12, %y = %y + 1
    var %y2 = %y1 + %y, %d2 = %d1 + %d
    while (%d2 &gt; $gettok(31 $iif((!$calc(%y2 % 400)) || (($calc(%y2 % 100)) &amp;&amp; (!$calc(%y2 % 4))),29,28) 31 30 31 30 31 31 30 31 30 31,%m2,32)) {
      var %d2 = %d2 - $v2, %m2 = %m2 + 1
      if (%m2 &gt; 12) var %m2 = %m2 - 12, %y2 = %y2 + 1
    }
  }
  elseif ($3 == past) {
    var %s2 = %s1 - %s
    while (%s2 &lt; 0) var %s2 = %s2 + 60, %n = %n - 1
    var %n2 = %n1 - %n
    while (%n2 &lt; 0) var %n2 = %n2 + 60, %h = %h - 1
    var %h2 = %h1 - %h
    while (%h2 &lt; 0) var %h2 = %h2 + 24, %d = %d - 1
    var %m2 = %m1 - %m
    while (%m2 &lt; 1) var %m2 = %m2 + 12, %y = %y - 1
    var %y2 = %y1 - %y, %d2 = %d1 - %d
    while (%d2 &lt; 1) {
      var %d2 = %d2 + $gettok(31 31 $iif((!$calc(%y2 % 400)) || (($calc(%y2 % 100)) &amp;&amp; (!$calc(%y2 % 4))),29,28) 31 30 31 30 31 31 30 31 30,%m2,32)
      var %m2 = %m2 - 1 | if (%m2 &lt; 1) var %m2 = %m2 + 12, %y2 = %y2 - 1
    }
  }
  else return uhm, you want the third parameter to be future or past...
  if (u isin $4) return $+($base(%m2,10,10,2),/,$base(%d2,10,10,2),/,$base(%y2,10,10,4) $base(%h2,10,10,2),:,$base(%n2,10,10,2),:,$base(%s2,10,10,2))
  return $+($base(%d2,10,10,2),/,$base(%m2,10,10,2),/,$base(%y2,10,10,4) $base(%h2,10,10,2),:,$base(%n2,10,10,2),:,$base(%s2,10,10,2))
}

alias datediff {
  ; calculate difference between date 1 and date 2, in years,months,(weeks),days,hours,minutes,seconds
  ; usage $datediff(dd/mm/yyyy HH:nn:ss, dd/mm/yyyy HH:nn:ss)
  ; meaning $datediff($date $time, $date $time)
  ; example:  //echo -a $datediff(3/5/2005 20:00:10, 5/10/2000 12:15:20)
  ; ** IMPORTANT: $date uses dd/mm/yyyy, if you want to input mm/dd/yyyy style, 
  ; **   add a third parameter 'u'
  ; other parameters
  ;  w = use weeks
  ;  a = display all fields, also 0 values
  ;  s = short duration identifiers
  ;  n = no spaces between numbers and durations
  ;  d = only numbers, no durations (use 'a' too or you won't have a clue what it means ;)
  ;  z = zeropad fields years(4) months(2) weeks(1) days(1) hours(2) minutes(2) seconds(2)
  ; example:  //echo -a $datediff(1/5/2005 11:15:22pm, 1/8/2005 12:15:22P.M., uws)
  ; hh:nn:ss am/pm is supported (only now I realize how strange it actually is)
  ; my reference: http://www.worldtimezone.com/wtz-names/wtz-am-pm.html

  var %1 = $1, %2 = $2, %switched = $false
  :dateswitch
  if ($regex(%2,/^0*(\d+)\D0*(\d+)\D(\d+)\D0*(\d+)\D0*(\d+)\D0*(\d+)(?:\D?([ap]\.?m\.?|noon|midday|midnight))?$/i)) {
    var %d1 = $regml($iif(u isin $3,2,1)), %m1 = $regml($iif(u isin $3,1,2))
    var %h1 = $regml(4), %n1 = $regml(5), %s1 = $regml(6), %y1 = $regml(3)
    if ((%h1 == 12) &amp;&amp; (($regml(7) == am) || ($v1 == midnight))) var %h1 = 0
    elseif ((%h1 isnum 1-11) &amp;&amp; ($regml(7) == pm)) inc %h1 12
  }
  else return Date 1 in incorrect format
  if ($regex(%1,/^0*(\d+)\D0*(\d+)\D(\d+)\D0*(\d+)\D0*(\d+)\D0*(\d+)(?:\D?([ap]\.?m\.?|noon|midday|midnight))?$/i)) {
    var %d2 = $regml($iif(u isin $3,2,1)), %m2 = $regml($iif(u isin $3,1,2))
    var %h2 = $regml(4), %n2 = $regml(5), %s2 = $regml(6), %y2 = $regml(3)
    if ((%h2 == 12) &amp;&amp; (($regml(7) == am) || ($v1 == midnight))) var %h2 = 0
    elseif ((%h2 isnum 1-11) &amp;&amp; ($regml(7) == pm)) inc %h2 12
  }
  else return Date 2 in incorrect format
  if ((%m1 !isnum 1-12) || (%d1 !isnum 1-31) || (%h1 !isnum 0-23) || (%m1 !isnum 0-59) $&amp;
    || (%s1 !isnum 0-59)) return Date 1 invalid ( %y1 ; %m1 ; %d1 ; %h1 ; %n1 ; %s1 )
  if ((%m2 !isnum 1-12) || (%d2 !isnum 1-31) || (%h2 !isnum 0-23) || (%m2 !isnum 0-59) $&amp;
    || (%s2 !isnum 0-59)) return Date 2 invalid
  var %s = %s1 - %s2 | if (%s &lt; 0) var %s = %s + 60, %n1 = %n1 - 1
  var %n = %n1 - %n2 | if (%n &lt; 0) var %n = %n + 60, %h1 = %h1 - 1
  var %h = %h1 - %h2 | if (%h &lt; 0) var %h = %h + 24, %d1 = %d1 - 1
  var %d = %d1 - %d2
  if (%d &lt; 0) var %d = %d + $gettok(31 31 $iif((!$calc(%y1 % 400)) || (($calc(%y1 % 100)) $&amp;
    &amp;&amp; (!$calc(%y1 % 4))),29,28) 31 30 31 30 31 31 30 31 30,%m1,32), %m1 = %m1 - 1
  var %m = %m1 - %m2, %y = %y1 - %y2, %w
  if (%m &lt; 0) var %m = %m + 12, %y = %y - 1
  if (%y &lt; 0) { if (%switched) return ERROR | var %1 = $2, %2 = $1, %switched = $true | goto dateswitch }

  if ( w  isin $3) var %w = $int($calc(%d / 7)) weeks, %d = $calc(%d - 7 * %w)
  if ( z  isin $3) var %y = $base(%y,10,10,4), %m = $base(%m,10,10,2), %d = $base(%d,10,10,2), $&amp;
    %h = $base(%h,10,10,2), %n = $base(%n,10,10,2), %s = $base(%s,10,10,2)
  var %res = %y years %m months %w %d days %h hours %n minutes %s seconds
  if ((a !isin $3) &amp;&amp; ( $regsub(%res,/(?&lt;!\d)0 \w++/g,,%res) )) { }
  if ( s  isin $3) { var %res = $replace(%res,year,yr,month,mth,week,wk,hour,hr,minute,min,second,sec) }
  $null($regsub(%res,/(?&lt;!\d)(1 \w+)s(?!\w)/g,\1,%res))
  if ((n  isin $3) &amp;&amp; ( $regsub(%res,/(?&lt;=\d)\s+(?=\w)/g,,%res) )) { }
  if ((d  isin $3) &amp;&amp; ( $regsub(%res,/\w/g,,%res) )) { }
  return %res
}

Re: Making $duration include months/years #126267 29/07/05 05:41 PM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Ok, here is my updated script. It now has formatting options. You can choose which items to display and even throw in some color codes or other formatting if you choose. This also will automatically adjust the output to show the right duration even if you remove an item from the display.

Example (if you do this in July):

$datexpander(4wks 3days) = 1 month, and 1 day
$datexpander(4wks 3days,d) = 31 days

(i.e. It doesn't just show 3 days). It's interesting with only seconds displayed... of course, the output is limited by mIRC's number size limits.

I've also in the process made some changes to how things are handled.

Suggestions, comments, etc?

Code:
; *******************************************************************
; DateXpander Script
; by Riamus 2005
;
; Suggestions and ideas for improvement from mIRC.com's forum
;
; This script will take a standard $duration and make it include months and years
; based on the current date.
;
; For this script to be accurate, it is only meant to be used when the $duration is
; using today's date and counting backwards (such as an uptime $duration). It
; will still be really accurate (within 3 days) even if you use a $duration that isn't
; from the current date, but it won't be exact that way.
;
; Use: $DateXpander(value,format)
; "value" must be in the format of $duration
; "format" uses y = years, m = months, w = weeks, d = days, h = hours, n = minutes, s = seconds
; "format" can also contain other information such as colors.  Zero pad your colors!
; Note that commas are automatically inserted.  Any other formatting can be done
; manually with this.
;
; For questions about this script, contact Riamus on IRC -- #oldgames on irc.undernet.org
; *******************************************************************

alias DateXpander {
  unset %dx-dateoutput

  if ($1 isalpha || $1 isnum) {
    echo -a Error.  Use the same format as in $chr(36) $+ duration.
    halt
  }

  set %dx_weeks $iif($gettok($1-,1,119) isnum,$gettok($1-,1,119),0)
  set %dx_days $iif($gettok($gettok($1-,1,100),-1,32) isnum,$gettok($gettok($1-,1,100),-1,32),0)
  set %dx_hours $iif($gettok($gettok($1-,1,104),-1,32) isnum,$gettok($gettok($1-,1,104),-1,32),0)
  set %dx_minutes $iif($gettok($gettok($1-,1,109),-1,32) isnum,$gettok($gettok($1-,1,109),-1,32),0)
  set %dx_seconds $iif(sec isin $gettok($1-,$gettok($1-,0,32),32),$gettok($gettok($1-,$gettok($1-,0,32),32),1,115),0)
  set %dx_totaldays $calc(%dx_weeks * 7 + %dx_days)
  set %dx_outputdays %dx_totaldays

  set %dx_currentmonth $date(m)

  :monthstart
  if ($istok(12.10.7.5,%dx_currentmonth,46)) {
    set %dx_monthdays 30
  }
  elseif ($istok(11.9.8.6.4.2.1,%dx_currentmonth,46)) {
    set %dx_monthdays 31
  }
  elseif (%dx_currentmonth == 3 &amp;&amp; $calc($date(yyyy) % 4) != 0) {
    set %dx_monthdays 28
  }
  elseif (%dx_currentmonth == 3 &amp;&amp; $calc($date(yyyy) % 4) == 0) {
    set %dx_monthdays 29
  }
  if (%dx_totaldays &gt;= %dx_monthdays) {
    inc %dx_months
    dec %dx_totaldays %dx_monthdays
    if (%dx_currentmonth != 1) {
      dec %dx_currentmonth
    }
    else { set %dx_currentmonth 12 }
    inc %dx_totalmonths
    inc %dx_monthsdays %dx_monthdays
    if (%dx_totalmonths == 12) {
      inc %dx_yeardays %dx_monthsdays
      unset %dc_monthsdays
      unset %dx_totalmonths
    }
    goto monthstart
  }

  set %dx_years $int($calc(%dx_months / 12))
  dec %dx_months $calc(%dx_years * 12)
  set %dx_weeks $int($calc(%dx_totaldays / 7))
  set %dx_totaldays $calc(%dx_totaldays % 7)

  if ($2) {
    if (y !isin $2 &amp;&amp; %dx_years &gt; 0) {
      set %dx_months $calc(%dx_months + (%dx_years * 12))
      set %dx_years 0
    }
    if (m !isin $2 &amp;&amp; %dx_months &gt; 0) {
      set %dx_weeks $iif(%dx_years == 0,$int($calc((%dx_outputdays) / 7)),$int($calc((%dx_outputdays - %dx_yeardays) / 7)))
      set %dx_totaldays $iif(%dx_years == 0,$calc((%dx_outputdays) % 7),$calc((%dx_outputdays - %dx_yeardays) % 7))
    }
    if (w !isin $2 &amp;&amp; %dx_weeks &gt; 0) {
      set %dx_totaldays $calc(%dx_totaldays + (%dx_weeks * 7))
    }
    if (d !isin $2 &amp;&amp; %dx_days &gt; 0) {
      set %dx_hours $calc(%dx_hours + (%dx_days * 24))
    }
    if (h !isin $2 &amp;&amp; %dx_hours &gt; 0) {
      set %dx_minutes $calc(%dx_minutes + (%dx_hours * 60))
    }
    if (n !isin $2 &amp;&amp; %dx_minutes &gt; 0) {
      set %dx_seconds $calc(%dx_seconds + (%dx_minutes * 60))
    }
    set %dateoutput $replacex($2,y,$bytes(%dx_years,b) $iif(%dx_years == 1,year $+ $chr(44) $+ $chr(32),years $+ $chr(44) $+ $chr(32)),m,$bytes(%dx_months,b) $iif(%dx_months == 1,month $+ $chr(44) $+ $chr(32),months $+ $chr(44) $+ $chr(32)),w,$bytes(%dx_weeks,b) $iif(%dx_weeks == 1,week $+ $chr(44) $+ $chr(32),weeks $+ $chr(44) $+ $chr(32)),d,$bytes(%dx_totaldays,b) $iif(%dx_totaldays == 1,day $+ $chr(44) $+ $chr(32),days $+ $chr(44) $+ $chr(32)),h,$bytes(%dx_hours,b) $iif(%dx_hours == 1,hour $+ $chr(44) $+ $chr(32),hours $+ $chr(44) $+ $chr(32)),n,$bytes(%dx_minutes,b) $iif(%dx_minutes == 1,minute $+ $chr(44) $+ $chr(32),minutes $+ $chr(44) $+ $chr(32)),s,$bytes(%dx_seconds,b) $iif(%dx_seconds == 1,second $+ $chr(44) $+ $chr(32),seconds $+ $chr(44) $+ $chr(32)))
    set %dateoutput $left(%dateoutput,-1)
    if ($gettok(%dateoutput,0,32) &gt; 2) {
      set %dateoutput $instok(%dateoutput,$chr(32) $+ and,-2,32)
    }
  }

  unset %dx_*

  return %dateoutput
}


Invision Support
#Invision on irc.irchighway.net
Re: Making $duration include months/years #126268 29/07/05 05:44 PM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Just as a note. If you choose to use colors in the formatting section, be sure to zero pad the single digit colors. smile


Invision Support
#Invision on irc.irchighway.net
Re: Making $duration include months/years #126269 12/08/05 01:30 PM
Joined: Oct 2004
Posts: 8,327
Riamus2 Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,327
Ok, I've updated this to remove a few bugs I found in it.

Code:
; *******************************************************************
; DateXpander Script
; by Riamus 2005
;
; Suggestions and ideas for improvement from mIRC.com's forum
;
; This script will take a standard $duration and make it include months and years
; based on the current date.
;
; For this script to be accurate, it is only meant to be used when the $duration is
; using today's date and counting backwards (such as an uptime $duration). It
; will still be really accurate (within 3 days) even if you use a $duration that isn't
; from the current date, but it won't be exact that way.
;
; Use: $DateXpander(value,format)
; "value" must be in the format of $duration
; "format" uses y = years, m = months, w = weeks, d = days, h = hours, n = minutes, s = seconds
; "format" can also contain out information such as colors.  Note that commas are automatically
; inserted.  Any other formatting can be done manually with this.
;
; For questions about this script, contact Riamus on IRC -- #oldgames on irc.undernet.org
; *******************************************************************

alias DateXpander {
  unset %dateoutput

  if ($1 isalpha || $1 isnum) {
    echo -a Error.  Use the same format as in $chr(36) $+ duration.
    halt
  }

  set %dx_weeks $iif($gettok($1,1,119) isnum,$gettok($1,1,119),0)
  set %dx_days $iif($gettok($gettok($1,1,100),-1,32) isnum,$gettok($gettok($1,1,100),-1,32),0)
  set %dx_hours $iif($gettok($gettok($1,1,104),-1,32) isnum,$gettok($gettok($1,1,104),-1,32),0)
  set %dx_minutes $iif($gettok($gettok($1,1,109),-1,32) isnum,$gettok($gettok($1,1,109),-1,32),0)
  set %dx_seconds $iif(sec isin $gettok($1,$gettok($1,0,32),32),$gettok($gettok($1,$gettok($1,0,32),32),1,115),0)
  set %dx_totaldays $calc(%dx_weeks * 7 + %dx_days)
  set %dx_outputdays %dx_totaldays

  set %dx_currentmonth $date(m)

  :monthstart
  if ($istok(12.10.7.5,%dx_currentmonth,46)) {
    set %dx_monthdays 30
  }
  elseif ($istok(11.9.8.6.4.2.1,%dx_currentmonth,46)) {
    set %dx_monthdays 31
  }
  elseif (%dx_currentmonth == 3 &amp;&amp; $calc($date(yyyy) % 4) != 0) {
    set %dx_monthdays 28
  }
  elseif (%dx_currentmonth == 3 &amp;&amp; $calc($date(yyyy) % 4) == 0) {
    set %dx_monthdays 29
  }
  if (%dx_totaldays &gt;= %dx_monthdays) {
    inc %dx_months
    dec %dx_totaldays %dx_monthdays
    if (%dx_currentmonth != 1) {
      dec %dx_currentmonth
    }
    else { set %dx_currentmonth 12 }
    inc %dx_totalmonths
    inc %dx_monthsdays %dx_monthdays
    if (%dx_totalmonths == 12) {
      inc %dx_yeardays %dx_monthsdays
      unset %dc_monthsdays
      unset %dx_totalmonths
    }
    goto monthstart
  }

  set %dx_years $int($calc(%dx_months / 12))
  dec %dx_months $calc(%dx_years * 12)
  set %dx_weeks $int($calc(%dx_totaldays / 7))
  set %dx_totaldays $calc(%dx_totaldays % 7)

  if ($2) {
    if (y !isin $2 &amp;&amp; %dx_years &gt; 0) {
      set %dx_months $calc(%dx_months + (%dx_years * 12))
      set %dx_years 0
    }
    if (m !isin $2 &amp;&amp; %dx_months &gt; 0) {
      set %dx_weeks $iif(%dx_years == 0,$int($calc((%dx_outputdays) / 7)),$int($calc((%dx_outputdays - %dx_yeardays) / 7)))
      set %dx_totaldays $iif(%dx_years == 0,$calc((%dx_outputdays) % 7),$calc((%dx_outputdays - %dx_yeardays) % 7))
    }
    if (w !isin $2 &amp;&amp; %dx_weeks &gt; 0) {
      set %dx_totaldays $calc(%dx_totaldays + (%dx_weeks * 7))
    }
    if (d !isin $2 &amp;&amp; %dx_days &gt; 0) {
      set %dx_hours $calc(%dx_hours + (%dx_days * 24))
    }
    if (h !isin $2 &amp;&amp; %dx_hours &gt; 0) {
      set %dx_minutes $calc(%dx_minutes + (%dx_hours * 60))
    }
    if (n !isin $2 &amp;&amp; %dx_minutes &gt; 0) {
      set %dx_seconds $calc(%dx_seconds + (%dx_minutes * 60))
    }
    set %dateoutput $replacex($2,y,$bytes(%dx_years,b) $iif(%dx_years == 1,year $+ $chr(44) $+ $chr(32),years $+ $chr(44) $+ $chr(32)),m,$bytes(%dx_months,b) $iif(%dx_months == 1,month $+ $chr(44) $+ $chr(32),months $+ $chr(44) $+ $chr(32)),w,$bytes(%dx_weeks,b) $iif(%dx_weeks == 1,week $+ $chr(44) $+ $chr(32),weeks $+ $chr(44) $+ $chr(32)),d,$bytes(%dx_totaldays,b) $iif(%dx_totaldays == 1,day $+ $chr(44) $+ $chr(32),days $+ $chr(44) $+ $chr(32)),h,$bytes(%dx_hours,b) $iif(%dx_hours == 1,hour $+ $chr(44) $+ $chr(32),hours $+ $chr(44) $+ $chr(32)),n,$bytes(%dx_minutes,b) $iif(%dx_minutes == 1,minute $+ $chr(44) $+ $chr(32),minutes $+ $chr(44) $+ $chr(32)),s,$bytes(%dx_seconds,b) $iif(%dx_seconds == 1,second $+ $chr(44) $+ $chr(32),seconds $+ $chr(44) $+ $chr(32)))
    set %dateoutput $left(%dateoutput,-1)
  }
  else {
    if (%dx_years &gt; 1) { set %dateoutput %dateoutput $bytes(%dx_years,b) $+ _years }
    elseif (%dx_years == 1) { set %dateoutput %dateoutput $bytes(%dx_years,b) $+ _year }
    if (%dx_months &gt; 1) { set %dateoutput %dateoutput %dx_months $+ _months }
    elseif (%dx_months == 1) { set %dateoutput %dateoutput %dx_months $+ _month }
    if (%dx_weeks &gt; 1) { set %dateoutput %dateoutput %dx_weeks $+ _weeks }
    elseif (%dx_weeks == 1) { set %dateoutput %dateoutput %dx_weeks $+ _week }
    if (%dx_totaldays &gt; 1) { set %dateoutput %dateoutput %dx_totaldays $+ _days }
    elseif (%dx_totaldays == 1) { set %dateoutput %dateoutput %dx_totaldays $+ _day }
    if (%dx_hours &gt; 1) { set %dateoutput %dateoutput %dx_hours $+ _hours }
    elseif (%dx_hours == 1) { set %dateoutput %dateoutput %dx_hours $+ _hour }
    if (%dx_minutes &gt; 1) { set %dateoutput %dateoutput %dx_minutes $+ _minutes }
    elseif (%dx_minutes == 1) { set %dateoutput %dateoutput %dx_minutes $+ _minute }
    if (%dx_seconds &gt; 1) { set %dateoutput %dateoutput %dx_seconds $+ _seconds }
    elseif (%dx_seconds == 1) { set %dateoutput %dateoutput %dx_seconds $+ _second }

    unset %dx_*

    set %dateoutput $replace(%dateoutput,$chr(32),$chr(44) $+ $chr(32),_,$chr(32))
  }
  if ($gettok(%dateoutput,0,32) &gt; 2) {
    set %dateoutput $instok(%dateoutput,$chr(32) $+ and,-2,32)
  }
  unset %dx_*

  return %dateoutput
}


Invision Support
#Invision on irc.irchighway.net
Page 1 of 2 1 2