|
charneus Wizard
Joined: 19 Jun 2005 Posts: 1876 Location: California
|
Posted: Fri Aug 08, 2008 12:37 am
Scripting question... |
EDIT: Added the padleft/padright functions so people could actually use this script and fix it, hopefully.
Code: |
<?xml version="1.0" encoding="ISO-8859-1" ?>
<cmud>
<func name="padLeft" copy="yes">
<value>#return %repeat($Character, $Length - %len($String))$String</value>
<arglist>String, Length, Character</arglist>
</func>
<func name="padRight" copy="yes">
<value>#return $String%repeat($Character, $Length - %len($String))</value>
<arglist>String, Length, Character</arglist>
</func>
</cmud> |
I use the following functions to do time differentials in many of my scripts. However, there is one flaw in it I haven't quite figured out yet, and I'm hoping someone will know
how to fix it.
The format to display times is:
#SAY @dateformat(@timediff("yyyy|mm|dd|hh|nn|ss","yyyy|mm|dd|hh|nn|ss"))
An example... say I want to calculate how much time passes between July 31st, 2008 at 3:45 am and August 17, 2008 at 9:47 pm. I would enter the information in like so:
#SAY @dateformat(@timediff("2008|07|31|03|45|00","2008|08|17|21|47|00"))
which would correctly output:
16d 18:02:00 (16 days, 18 hours, 2 minutes)
Works great, except for the one tiny flaw. If the start time and the end time are just hours apart, but it crosses midnight, it adds a day to the output. This is only within the same month, though. For instance:
#SAY @dateformat(@timediff("2008|07|30|23|45|00","2008|07|31|02|00|00"))
instead of 2:15:00, it shows 1d 2:15:00. As you can see, that's totally incorrect. So, I'm hoping someone can find a fix for it. I greatly appreciate it!
Charneus
Code: |
<?xml version="1.0" encoding="ISO-8859-1" ?>
<cmud>
<class name="Functions" copy="yes">
<func name="dayOfWeek" copy="yes">
<value>#return %ismember($Day, "Sun|Mon|Tue|Wed|Thur|Fri|Sat")</value>
<arglist>Day</arglist>
</func>
<func name="timeDiff" copy="yes">
<value>#local $TimeInSeconds $Years $Months $Days $Hours $Minutes $Seconds
$TimeInSeconds = %eval( @timeSerial( %item( $EndTime, 4), %item( $EndTime, 5), %item( $EndTime, 6), %item( $EndTime, 3), %item( $EndTime, 2), %item( $EndTime, 1)) - @timeSerial( %item( $StartTime, 4), %item( $StartTime, 5), %item( $StartTime, 6), %item( $StartTime, 3), %item( $StartTime, 2), %item( $StartTime, 1)))
$Seconds = %eval( %mod( $TimeInSeconds, 60))
$Minutes = %eval( %mod( $TimeInSeconds, 3600) / 60)
$Hours = %eval( %mod( $TimeInSeconds, 86400) / 3600)
$Days = %item( $EndTime, 3) - %item( $StartTime, 3)
$Months = %item( $EndTime, 2) - %item( $StartTime, 2)
$Years = %item( $EndTime, 1) - %item( $StartTime, 1)
$Months = %eval( $Months - %eval( %if( $Days < 0, 1, 0)))
$Years = %eval( $Years - %eval( %if( $Months < 0, 1, 0)))
$Days = %eval( $Days + %eval( %if( $Days < 0, @daysInMonth( %item( $StartTime, 2), %item( $StartTime, 1)) - 1, 0)))
$Months = %eval( $Months + %eval( %if( $Months < 0, 12, 0)))
#return $Years|$Months|$Days|$Hours|$Minutes|$Seconds</value>
<arglist>StartTime, EndTime</arglist>
</func>
<func name="daysInMonth" copy="yes">
<value>#return %eval(%item(31|%if((%mod($Year, 4) == 0) AND (%mod($Year, 400) != 0), 29, 28)|31|30|31|30|31|31|30|31|30|31, $Month))</value>
<arglist>Month, Year</arglist>
</func>
<func name="dateSerial" copy="yes">
<value>#return %eval($Day + @daysTillMonth($Month, $Year) + 365 * $Year)</value>
<arglist>Day, Month, Year</arglist>
</func>
<func name="timeSerial" copy="yes">
<value>#if (%isnumber($Year))
{
#return %eval($Second + $Minute * 60 + $Hour * 3600 + 86400 * @dateSerial($Day, $Month, $Year))
} {
#return %eval($Second + $Minute * 60 + $Hour * 3600)
}</value>
<arglist>Hour, Minute, Second, Day, Month, Year</arglist>
</func>
<func name="daysTillMonth" copy="yes">
<value>#if (!%isnumber($ThisMonth))
{
$ThisMonth = 1
}
#if ($Month > $ThisMonth)
{
#return %eval(@daysInMonth($ThisMonth, $Year) + @daysTillMonth($Month, $Year, %eval($ThisMonth + 1)))
} {
#return 0
}</value>
<arglist>Month, Year, ThisMonth</arglist>
</func>
<func name="dateFormat" copy="yes">
<value><![CDATA[#if (@dateSerial(%item($Time, 3), %item($Time, 2) + 1, %item($Time, 1)) > 0)
{
#return %if(%item($Time, 1) > 0, %item($Time, 1)"y ")%if(@dateSerial(0, %item($Time, 2) + 1, %item($Time, 1)) > 0, %item($Time, 2)"m ")%if(@dateSerial(%item($Time, 3), %item($Time, 2) + 1, %item($Time, 1)) > 0, %item($Time, 3)"d ")@padLeft(%item($Time, 4),2,0)":"@padLeft(%item($Time, 5),2,0)":"@padLeft(%item($Time, 6),2,0)
} {
#return %if(%item($Time, 4) > 0, @padLeft(%item($Time, 4),2,0)":")@padLeft(%item($Time, 5),2,0)":"@padLeft(%item($Time, 6),2,0)
}]]></value>
<arglist>Time</arglist>
</func>
<func name="timeFormat" copy="yes">
<value>$Seconds = %eval(%mod($TimeInSeconds, 60))
$Minutes = %eval(%mod($TimeInSeconds, 3600) / 60)
$Hours = %eval(%mod($TimeInSeconds, 86400) / 3600)
$Days = 0//%item($EndTime, 3) - %item($StartTime, 3)
$Months = 0//%item($EndTime, 2) - %item($StartTime, 2)
$Years = 0//%item($EndTime, 1) - %item($StartTime, 1)
$Months = 0//%eval($Months - %eval(%if($Days < 0, 1, 0)))
$Years = 0//%eval($Years - %eval(%if($Months < 0, 1, 0)))
$Days = 0//%eval($Days + %eval(%if($Days < 0, @daysInMonth(%item($StartTime, 2), %item($StartTime, 1)) - 1, 0)))
$Months = 0//%eval($Months + %eval(%if($Months < 0, 12, 0)))
#return $Years|$Months|$Days|$Hours|$Minutes|$Seconds</value>
<arglist>TimeInSeconds</arglist>
</func>
</class>
</cmud> |
|
|
Last edited by charneus on Mon Aug 11, 2008 3:28 am; edited 1 time in total |
|
|
|
Seb Wizard
Joined: 14 Aug 2004 Posts: 1269
|
Posted: Fri Aug 08, 2008 3:13 am |
We should get Zugg to add a proper DateDiff function to CMUD - I have a TimeDiff function I made for zMUD that works fine, but it doesn't do anything greater than 24 hours, or well, it does, but it only gives you the hours, minutes and seconds, so days and months etc. get taken off (which is fine for my needs).
But the Diff part is very simple on mine: I work out the number of seconds since midnight on both times and then:
%if( %2>%1, %eval( %2-%1), %eval( (%2+86400)-%1))
and this fixes the crossing midnight problem. (And then reconvert the difference in seconds to hours, minutes and seconds.) |
|
|
|
Arde Enchanter
Joined: 09 Sep 2007 Posts: 605
|
Posted: Fri Aug 08, 2008 7:47 am |
Seb:
yeah, that would be nice to have such a function.
charneus:
Meanwhile, you can use script that Dharkael posted in this forum not so long ago. Search for "time difference" to find it. |
|
_________________ My personal bug|wish list:
-Wrong Priority when copy-paste setting
-1 prompt trigger for Mapper, Session and General Options, not 3 different!
-#SECTION can terminate threads
-Buttons can't start threads |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Fri Aug 08, 2008 12:57 pm |
http://forums.zuggsoft.com/forums/viewtopic.php?t=30787
It's the one that you've already seen charneus and for some reason you have a JScript problem.
Arde: What's wrong with your #SAY %int(%number(%time("mmddhhnnss"))) it seems to work quite well? Especially if you use #SAY %int(%number(%time("yyymmddhhnnss"))) |
|
_________________ Taz :) |
|
|
|
charneus Wizard
Joined: 19 Jun 2005 Posts: 1876 Location: California
|
Posted: Fri Aug 08, 2008 11:31 pm |
Using a different script would be fine and dandy - only if so many of my other scripts didn't depend on this one. It seems like it should be a simple fix. I just can't figure it out. :(
Charneus |
|
|
|
Rahab Wizard
Joined: 22 Mar 2007 Posts: 2320
|
Posted: Sun Aug 10, 2008 5:49 pm |
Calculating differences in time is actually quite tricky. I've worked with time calculations for astronomy (where it gets even trickier because of multiple time standards!), so I know how complicated it can get. If you look at your code, it adjusts the month difference if the day difference is negative, and similarly adjusts the year difference if the month difference is negative. But you don't adjust the day difference based on the difference in hours, minutes, and seconds. And that is not the only problem. Imagine you have two dates, May 1 2:00, and June 1 1:00. I believe your calculation will say they are nearly two months apart instead of one, because you don't check the difference in hours, minutes, and seconds. A similar problem can occur with differences in years.
The easiest way to avoid all of these complicated %if statements is to convert each time into a number of seconds after some fixed point in time, and simply subtract. If you don't want to pick some fixed point in time, you can instead convert them into a year plus a number of seconds into the year. Then you will only have to worry about a single check on negative differences. |
|
|
|
Arde Enchanter
Joined: 09 Sep 2007 Posts: 605
|
Posted: Sun Aug 10, 2008 10:45 pm |
Taz
I can't remember now: I figured out that script was bad and have forget about it Hmm... If you'll take 2 different times, for ex., 09:23:55 and 09:24:05, then difference between them should be 10 seconds, but my script will show 50 seconds difference (405-355=50). |
|
_________________ My personal bug|wish list:
-Wrong Priority when copy-paste setting
-1 prompt trigger for Mapper, Session and General Options, not 3 different!
-#SECTION can terminate threads
-Buttons can't start threads |
|
|
|
charneus Wizard
Joined: 19 Jun 2005 Posts: 1876 Location: California
|
Posted: Mon Aug 11, 2008 3:24 am |
Rahab wrote: |
Calculating differences in time is actually quite tricky. I've worked with time calculations for astronomy (where it gets even trickier because of multiple time standards!), so I know how complicated it can get. If you look at your code, it adjusts the month difference if the day difference is negative, and similarly adjusts the year difference if the month difference is negative. But you don't adjust the day difference based on the difference in hours, minutes, and seconds. And that is not the only problem. Imagine you have two dates, May 1 2:00, and June 1 1:00. I believe your calculation will say they are nearly two months apart instead of one, because you don't check the difference in hours, minutes, and seconds. A similar problem can occur with differences in years.
The easiest way to avoid all of these complicated %if statements is to convert each time into a number of seconds after some fixed point in time, and simply subtract. If you don't want to pick some fixed point in time, you can instead convert them into a year plus a number of seconds into the year. Then you will only have to worry about a single check on negative differences. |
Actually...
#say @dateformat(@timediff("2008|05|01|02|00|00","2008|06|01|01|00|00"))
returns
1m 0d 23:00:00... not nearly two months apart, but a day too long. It should read 30d 23:00:00. Bah. So it's just the day that screws things up, I guess... *sigh*
Charneus |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Mon Aug 11, 2008 1:36 pm |
Arde wrote: |
Taz
I can't remember now: I figured out that script was bad and have forget about it Hmm... If you'll take 2 different times, for ex., 09:23:55 and 09:24:05, then difference between them should be 10 seconds, but my script will show 50 seconds difference (405-355=50). |
Doh! Of course dates and time are not decimal so you can't get the actual correct time difference from that subtraction. Silly me, my brain was certainly not in gear that day.
charneus: I'm also getting the JScript error. It says it the first time and then it says something about VBScript parse error. I'm going to get some screenies and steps and post something as it seems a little wrong to me. |
|
_________________ Taz :) |
|
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|