AutoHotkey Community

It is currently May 25th, 2012, 1:19 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 31 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
 Post subject:
PostPosted: July 26th, 2007, 9:35 am 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5346
Location: UK
Skan wrote:
The age between A_Now and A_Now + 1 Second will yield 00000000000001 which is not a valid DateTime stamp.
You asked for "Even better, I need the function to return me the age as a DateTime Stamp like: 00020318074330" which that does, am I wrong?

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 10:10 am 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8775
BoBo¨ wrote:
I guess Skan is looking for a YourLive_TickCount, right?


My requirement is not that simple. I require it for Sidereal Astrology where the internal calculations are perfect, but I am not able to report the correct age between two time slices.

I would be having around 531441 ( 9^6 ) time slices in a report.

:)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 10:14 am 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8775
Titan wrote:
am I wrong?


No not at all. Its just that the returned string cannot always be a valid Datetime stamp. For example: Difference between my original birthdate and this year's is returned as 00360000000000 which I cannot format with FormatTime. So Age() has to return the string preformatted/delimited.

Thanks :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 8:45 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
As said, there is no perfect solution. It does not mean, you have to abandon the idea. If you don't mind occasional unintuitive results, here is a script to experiment with. It was left un-optimized (can reduce to half size) to help tuning it to your liking. The algorithm is the following:

- If the day|time value in the start date is less than that at the end, determine the number of years and months from the start to the same day|time point in the end-month. The remaining days and time can be computed normally.

- Otherwise, take the month preceding the end-month, and look at the day|time point here, identical to that of the start day|time. If it exists, compute the number of years and months to this day, and the days and time until the desired end-date from here (which is always less than a month)

- If this day in the second last month does not exist (like February 30th), take the last day of this month, instead.

Test it with many extreme values, and post the results you don't like. One interesting result is from March 1 till next year's February 29 (365 days) there seem to be 11 months and 28 days, because till February 1 there are 11 months, and 28 days remained.
Code:
MsgBox % Age("19990301000000", "20000229000000") ; 11 months 28 days
MsgBox % Age("20000130000000", "20000331000000") ;  2 months  1 day
MsgBox % Age("20000131000000", "20000330000000") ;  1 month  30 days
MsgBox % Age("20000131000000", "20000301000000") ;  1 month   1 day
MsgBox % Age("20000130000000", "20000301000000") ;  1 month   1 day
MsgBox % Age("20000129000000", "20000301000000") ;  1 month   1 day
MsgBox % Age("20000128000000", "20000301000000") ;  1 month   2 days
MsgBox % Age("20010128000000", "20010301000000") ;  1 month   1 day
MsgBox % Age("20050407041630", "20070725120000") ; 2 years 3 months 18 days 7 hours 43 minutes 30 seconds

Age(BeginT,EndT) {
   FormatTime  B, %BeginT%,yyyy|MM|ddHHmmss
   StringSplit B,  B,  |   ; 1  2  3
   FormatTime  E, %EndT%,  yyyy|MM|ddHHmmss
   StringSplit E,  E,  |

   If (B3 <= E3) {         ; begin day.time is earlier than end day.time
      dY := E1 – B1 – (E2<B2)
      dM := Mod(12+E2-B2, 12)
      D  := E1 . E2 . B3
   } Else {                ; go back to the previous month
      D := E1 . E2         ; 1st day of end month
      D += -1, D           ; last day of previous month
      FormatTime  D, %D%, yyyy|MM|dd|HHmmss
      StringSplit D,  D, | ; 1  2  3  4
      If (D3 <= SubStr(B3,1,2)) { ; have to take the last day of prev. month
          dY := D1 – B1 – (D2<B2)
          dM := Mod(12+D2-B2, 12)
          D := D1 . D2 . D3 . SubStr(B3,-5)
      } Else {                    ; take begin's day.time
          dY := D1 – B1 – (D2<B2)
          dM := Mod(12+D2-B2, 12)
          D := D1 . D2 . B3
      }
   }
   EndT -= D, S
   T := 2000               ; ~ 0 (with 1 day offset)
   T += EndT, S            ; formatted to ...ddHHmmss
   Return dY " " dM " " SubStr(T,7,2)-1 " " SubStr(T,9,2) " " SubStr(T,11,2) " " SubStr(T,-1)
}


Edit 20070727: fixed small time difference (0 days insted of 31)


Last edited by Laszlo on July 27th, 2007, 5:05 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 8:48 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8775
Wow! Thank you sir. I will try it. :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject: TimeDateStamp
PostPosted: July 27th, 2007, 11:04 am 
Offline

Joined: July 6th, 2004, 10:07 am
Posts: 171
Location: Manchester, England.
@Skan
Firstly some preamble. In astrology and astronomy the former being the forerunner of the latter, it is customary to use a unified system of measurement ie: for time Utc + delta T for ET and julian day serials.
However if you are satisfied that 1601 -> 2099 are not limiting factors then AHK's built-in functions are completely adequate. I personally use the former methods.
The fact that you have ended up in this seemingly intractable problem, leads me to believe that you may not have chosen the best methodology. However that aside, lets tackle the problem as you have presented it.

Data provided.
Begin := "20050407041630" ; April, 7 2005 4:16:30 AM
End := "20070725120000" ; July , 25 2007 12:00:00 PM

Equates to: 839 days 7 hours 43 minutes 30 seconds
Absolutely Correct.

But where the problem begins is where you try to convert the 839 days, because any conversion you do with the 839 is going to end up as an incorrect solution.

BUT THERE IS A CORRECT SOLUTION.

Consider your answer above: it also equates to 72517410 seconds

However you're working from right to left to produce '00020318074330' which when evaluated produces 72587610 seconds which is in error by -19.5 hours.

The correct answer using this format is '00020317121330' which is arrived at by working from left to right and produces the correct answer of 72517410 seconds.

Aha, I hear you say, but where's the solution. Well I've only just picked up on this problem and unfortunately I will not be at home for the rest of the day. However upon my return I will endeavour to convert the formulae into AHK and forward to you A.S.A.P.

Regards Dave.

_________________
Simple ideas lie within reach, only of complex minds


Report this post
Top
 Profile  
Reply with quote  
 Post subject: Re: TimeDateStamp
PostPosted: July 27th, 2007, 4:12 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Dippy46 wrote:
where the problem begins is where you try to convert the 839 days, because any conversion you do with the 839 is going to end up as an incorrect solution.

BUT THERE IS A CORRECT SOLUTION.
Yes, in the sense that we can choose an algorithm an define its output as the "age"; No, in the sense that the you cannot measure something unambiguously with units of changing size.
Dippy46 wrote:
'00020318074330' which when evaluated produces 72587610 seconds
You cannot convert this to seconds, knowing nothing about the length of those two years and three months.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 27th, 2007, 4:55 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
The average length of the Gregorian year is 365.2425 days, but in astronomy, the best measure of the length of the year is the sidereal year: the time for the Earth to complete one revolution of its orbit, measured in the reference of the fixed stars. Its duration in SI days of 24*60*60 = 86400 SI seconds each is on average:

365.256363051 days (365 days 6 hours 9 minutes 9 seconds), when started at 2000 January 1 12:00:00 TT. It makes 365.256363051*86400 = 31558149.7676064 seconds.

For convenience, one can divide this time into 12 months, each having 31558149.7676064/12 = 2629845.8139672 seconds.

These lead to another algorithm to calculate "Age", which is accurate in the average, for large time differences:
Code:
Ys = 31558149.7676064 ; average  year in seconds
Ms =  2629845.8139672 ; average month in seconds

B = 20050407041630    ; date|time of the beginning
E = 20070725120000    ; date|time of the end

E -= B,s              ; 72517410 seconds difference
Y := Floor(E/Ys)      ; = years in the average
E -= Y*Ys
M := Floor(E/Ms)      ; + months in the average
E -= M*Ms
D  = 2000             ; ~ day 0 (count from ..01000000)
D += E,s
D := SubStr(d,-7)-1000000
MsgBox %Y% %M% %D%
The result is 2 3 17115253, which is unintuitive for small age values, but correct in the average.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 27th, 2007, 5:10 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Fixed a bug in my prior-month based script, which showed 31 days instead of 0.


Report this post
Top
 Profile  
Reply with quote  
 Post subject: DateTimeStamp
PostPosted: July 27th, 2007, 5:56 pm 
Offline

Joined: July 6th, 2004, 10:07 am
Posts: 171
Location: Manchester, England.
@Laszlo , Glad you saw the light....

_________________
Simple ideas lie within reach, only of complex minds


Report this post
Top
 Profile  
Reply with quote  
 Post subject: DateTimeStamp
PostPosted: July 27th, 2007, 6:01 pm 
Offline

Joined: July 6th, 2004, 10:07 am
Posts: 171
Location: Manchester, England.
@Skan

@Skan

Ok here we go!

Of course if you needed to use the timestamp as I've provided with FormatTime then as you say the first digit would have to be a '9' see program below.
This is about as far as I can take it given the information you provided ! Also I'm not sure on speed considerations. If this turns out not to be what you wanted then I can only suggest that you re-evaluate the methodology or consider re-describing the problem.

Code:
Begin  := "20050407041630" ; April,  7 2005  4:16:30 AM
End    := "20070725120000" ; July , 25 2007 12:00:00 PM

_= Show TimeStamp (Tds) of Diff for given Dates

 MsgBox % "Date Diff TimeStamp `n`n" Gft(Begin,End)

_= Convert Tds to Seconds For given dates

 DiffSec:= TdsToSec(Gft(Begin,End))
 MsgBox % "Date Diff in seconds `n`n" DiffSec

_= Function Proofs

_= 1 Show Begin+Tds ie: End

 EnvAdd,Begin,DiffSec,S
 MsgBox % "Begin + DiffSec = End Date = " Begin

_= 2 Show End-Tds ie: Begin

 Envadd,End,-DiffSec,S
 MsgBox % "End - DiffSec = Begin Date = " End

_= Hence '00020318074330' produces the wrong answer
 MsgBox % "Wrong Answer: `n`n" TdsToSec(00020318074330)

_= as per your original request verbatim!

  Age := "9" SubStr(Gft(Begin,End),2)
  FormatTime, Time, %Age%, yy-MM-dd|H:m:s ; Which is a Term of Duration.
  MsgBox % "Duration: `n`n" Time


_= ====================================================================
 Gft(_d1,_d2)
   {
   EnvSub,_d1,_d2,S
   v1:=Abs(_d1)
   Syr:=31557600,Smt:=2629800,Sdy:=86400,Shr:=3600,Smi:=60
   yr:= Floor(v1/Syr),v2:=Mod(v1,Syr),mt:= Floor(v2/Smt),v3:=Mod(v2,Smt)
   dy:= Floor(v3/Sdy),v4:=Mod(v3,Sdy),hr:= Floor(v4/Shr),v5:=Mod(v4,Shr)
   mi:= Floor(v5/Smi),v6:=Mod(v5,Smi),se:= v6
   Return % Pad(yr,4) Pad(mt,2) Pad(dy,2) Pad(hr,2) Pad(mi,2) Pad(se,2)
   }
_= ====================================================================

_= --------------------------------------------------------------------
 Pad(_Var,_Len)
   {
   Pd:="0000"
   Return % SubStr(Pd,1,_Len-StrLen(_Var)) _Var
   }
_= --------------------------------------------------------------------
 TdsToSec(_Age)
   {
   Syr:=31557600,Smt:=2629800,Sdy:=86400,Shr:=3600,Smi:=60
   yr:=Substr(_Age,1,4) * Syr,mt:=Substr(_Age,5,2) * Smt
   dy:=Substr(_Age,7,2) * Sdy,hr:=Substr(_Age,9,2) * Shr
   mi:=Substr(_Age,11,2)* Smi,se:=Substr(_Age,13,2)* 1
   Return % yr+mt+dy+hr+mi+se ; seconds
   }
_= --------------------------------------------------------------------


Regards Dave.

_________________
Simple ideas lie within reach, only of complex minds


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 27th, 2007, 6:33 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
This is a more complex variant of the average year/month script posted before, with less accurate constants. The user has to decide, which definition of year-length to use. Here it is set to 365.25 days, which is between the Gregorian and sidereal year. The difference is a few hundred seconds a year, less than 2 seconds a day.

The comment " '00020318074330' produces the wrong answer" is, of course, false. It does not give the wrong answer, but a different one, which makes more sense for small ages.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 27th, 2007, 7:20 pm 
Offline

Joined: July 6th, 2004, 10:07 am
Posts: 171
Location: Manchester, England.
@Laszlo

The less accurate constants you refer to are those generally accepted by the astronomical community eg: NASA and by the world's foremost expert on the subject, namely 'Jean Meeus'. I assumed from the the request that an accurate calculation was required. The routines provide 1 second of accuracy even if the offset between the 2 dates is only 1 second. The problem only occurs when the FormatTime function is invoked which, in my opinion, in this case is not required. The following routine circumvents the problem...

Code:

  Age := SubStr(Gft(Begin,End),1)
  MsgBox % SubStr(Age,3,2) "-" SubStr(Age,5,2) "-" SubStr(Age,7,2) "|" SubStr(Age,9,2) ":" SubStr(Age,11,2) ":" SubStr(Age,13,2)




The number I quoted as being wrong IS wrong in the context of the described requirements. The normal method to arrive at the correct answer would be as follows.

Using Julian Day Notation

Code:

Begin := 2453467.67812 ;  April,  7 2005  4:16:30 AM
End   := 2454307.00000 ;  July , 25 2007 12:00:00 PM

Duration  = (IntPart(End-Begin)*86400)+(86400*FracPart(End-Begin)) = 72517410 Secs



QED.

Regards Dave.

_________________
Simple ideas lie within reach, only of complex minds


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 27th, 2007, 10:07 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8775
@ Laszlo / Dave

Dear Sirs, :)

Thanks for all the input.

I have been trying to create a function that will exactly reproduce the manual calculation ( the one I do with a Pen-Paper-Calender )
Since it is hard to check various dates manually, I thought of using a slower version ( which will loop through each month of the period to get an exact count of Y,M,D ) to compare the results with your functions.
Unbelievably, I am unable to make it accurate and the function misses a day or two :cry:

Please allow me one more day before I can post my results.

Thanks again for all the help and professional input.

Best Regards. :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject: TimeDateStamp
PostPosted: July 27th, 2007, 10:47 pm 
Offline

Joined: July 6th, 2004, 10:07 am
Posts: 171
Location: Manchester, England.
@Skan

Yes I think the answer mainly lies in one of my previous statements.


Quote:
Equates to: 839 days 7 hours 43 minutes 30 seconds
Absolutely Correct.

But where the problem begins is where you try to convert the 839 days, because any conversion you do with the 839 is going to end up as an incorrect solution.



And as I explained, the number that you provided in your example which supposedly was manually calculated, was also out by -19.5 hours.

Though it would be possible as you say to analyse the months to which the period referred, once it had been converted to a number, it would then be irreversable due to the fact that the original months involved would now be unknown. This would also seriously affect your prime objective which we were told was that of speed ????

Regards Dave.

_________________
Simple ideas lie within reach, only of complex minds


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 31 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: azure, KenC, krajan, Pulover, toddintr and 26 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group