Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Code to convert from/to UNIX timestamp.


  • Please log in to reply
21 replies to this topic
CarlosTheTackle
  • Members
  • 102 posts
  • Last active: Jan 29 2007 12:07 PM
  • Joined: 19 Oct 2004
Ok, I need to deliver some timestamp info to another utility in UNIX timestamp format (which is number of seconds since Jan 1, 1970). Has anyone already written the code in AutoHotkey to do this conversion from AHKs YYYYMMDDHHMISS format? I could probably do it, but it seems like it'll be quite tedious, so if anyone's already done this, then why not share the love, right?

If no one else has done it then I guess I'll bite the bullet and figure it out. I'll post my code here in a couple of days if I get it sorted. I imagine the only tricky bit will be allowing for leap years.

P.S. Chris, this might be a good built-in function for the AHK 'Transform' command in the future.

Cheers guys,

C.


Update: Ok, here's what I got. And it didn't take too long at all. Seems to work so far. If anyone can see any mistakes or ways to improve its efficiency, please point them out.
It only goes one way (AHK to Unix - maybe someone else can do the reverse some time?), and will work for dates between 1970 and 2400.


;###############Convert YYYYMMDDHHMISS into Unix timestamp#############

time_orig=%A_NOW%

StringLeft, now_year, time_orig, 4
StringMid, now_month, time_orig, 5, 2
StringMid, now_day, time_orig, 7, 2
StringMid, now_hour, time_orig, 9, 2
StringMid, now_min, time_orig, 11, 2
StringRight, now_sec, time_orig, 2

;Get year seconds
year_sec := 31536000*(now_year - 1970)

;Determine how many leap days
leap_days := (now_year - 1972)/4 + 1
Transform, leap_days, Floor, %leap_days%

;Determine if date is in a leap year, and if the leap day has been yet
this_leap := now_year/4
Transform, this_leap_round, Floor, %this_leap%
If (this_leap = this_leap_round)
  {
  If now_month <= 2
    leap_days--   ;subtracts 1 because this year's leap day hasn't been yet
  }
leap_sec := leap_days*86400

;Determine fully completed months
If now_month = 01
  month_sec = 0
If now_month = 02
  month_sec = 2678400
If now_month = 03
  month_sec = 5097600
If now_month = 04
  month_sec = 7776000
If now_month = 05
  month_sec = 10368000
If now_month = 06
  month_sec = 13046400
If now_month = 07
  month_sec = 15638400
If now_month = 08
  month_sec = 18316800
If now_month = 09
  month_sec = 20995200
If now_month = 10
  month_sec = 23587200
If now_month = 11
  month_sec = 26265600
If now_month = 12
  month_sec = 28857600

  
;Determine fully completed days
day_sec := (now_day - 1)*86400

;Determine fully completed hours
hour_sec := now_hour*3600 ;don't subtract 1 because it starts at 0

;Determine fully completed minutes
min_sec := now_min*60

;Calculate total seconds
date_sec := year_sec + month_sec + day_sec + leap_sec + hour_sec + min_sec + now_sec
MsgBox, %date_sec%


Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Thanks for sharing that.

UNIX timestamp format (which is number of seconds since Jan 1, 1970...
...this might be a good built-in function for the AHK 'Transform' command in the future.

I would add it if it were available in the Windows API. Since I don't think it is, the problem is that the C library would have to be used to get it, which I think increases the code size. In other words, every compiled script might be increased by 1 or 2 KB by adding such a variable.

It could also be added by reproducing your script's functionality in the program, but this seems like too rare a need to justify the extra code. However, if others want it too, perhaps they will post here to let me know.

Since you posted your solution, I'll move this topic to the Scripts forum so that it will be easier to find in the future.

Thanks.

CarlosTheTackle
  • Members
  • 102 posts
  • Last active: Jan 29 2007 12:07 PM
  • Joined: 19 Oct 2004

It could also be added by reproducing your script's functionality in the program, but this seems like too rare a need to justify the extra code.

Yeah, people can just grab it from here if they need it. I agree, don't bloat the core code.

Cheers.

BoBo
  • Guests
  • Last active:
  • Joined: --

A_YDay Current day of the year (1-366). The value is not zero-padded, e.g. 9 is retrieved, not 009. To retrieve a zero-padded value, use the following: FormatTime, OutputVar, , YDay0

A_YWeek Current year and week number according to ISO 8601. Example: 200453. To separate the year from the week, use StringLeft and StringRight. Definition of week number: If the week containing January 1st has four or more days in the new year, it is considered week 1. Otherwise, it is the last week of the previous year, and the next week is week 1. [requires v1.0.24+]

Wouldn't it be possible to use one of the above commands to check/get a leap year ???

CarlosTheTackle
  • Members
  • 102 posts
  • Last active: Jan 29 2007 12:07 PM
  • Joined: 19 Oct 2004
With the release of AHK 1.0.31.0 I have now restructured this conversion as a function which anyone can call when needed:
;This function takes an input timestamp in the form YYYYMMDDHHMISS and converts
;it into a UNIX standard epoch timestamp (ie. The number of seconds since
;Jan 1, 1970). It will only work for dates from 1970 to 2400 (which is the next
;year in which the leap year rules are different).
;If you feed in an incorrectly formatted parameter the function will
;return a string detailing the error.

UnixTimeStamp(time_orig)
{
;Check that input parameter is correct format.
StringLen, date_len, time_orig
If date_len<>14
  return "The input parameter has incorrect length or is an incorrect number format."
If time_orig is not integer
  return "The input parameter is an incorrect number format."

;Split date into useable parts
StringLeft, now_year, time_orig, 4
StringMid, now_month, time_orig, 5, 2
StringMid, now_day, time_orig, 7, 2
StringMid, now_hour, time_orig, 9, 2
StringMid, now_min, time_orig, 11, 2
StringRight, now_sec, time_orig, 2

;Get year seconds
year_sec := 31536000*(now_year - 1970)

;Determine how many leap days
leap_days := (now_year - 1972)/4 + 1
Transform, leap_days, Floor, %leap_days%

;Determine if date is in a leap year, and if the leap day has been yet
this_leap := now_year/4
Transform, this_leap_round, Floor, %this_leap%
If (this_leap = this_leap_round)
  {
  If now_month <= 2
    leap_days--   ;subtracts 1 because this year's leap day hasn't been yet
  }
leap_sec := leap_days*86400

;Determine fully completed months
If now_month = 01
  month_sec = 0
If now_month = 02
  month_sec = 2678400
If now_month = 03
  month_sec = 5097600
If now_month = 04
  month_sec = 7776000
If now_month = 05
  month_sec = 10368000
If now_month = 06
  month_sec = 13046400
If now_month = 07
  month_sec = 15638400
If now_month = 08
  month_sec = 18316800
If now_month = 09
  month_sec = 20995200
If now_month = 10
  month_sec = 23587200
If now_month = 11
  month_sec = 26265600
If now_month = 12
  month_sec = 28857600

  
;Determine fully completed days
day_sec := (now_day - 1)*86400

;Determine fully completed hours
hour_sec := now_hour*3600 ;don't subtract 1 because it starts at 0

;Determine fully completed minutes
min_sec := now_min*60

;Calculate total seconds
date_sec := year_sec + month_sec + day_sec + leap_sec + hour_sec + min_sec + now_sec

return date_sec
}


Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Nice. That's an ideal use of a function. Now anyone can use #include (or copy it directly into a script) and call it to get a simple time conversion.

Thanks for posting it.

Mykron23
  • Guests
  • Last active:
  • Joined: --
I am beginner at using AHK and this has me stumped. How can I call this function for the timestamp?

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Actually, the following single line computes the Unix timestamp.
T := 31536000*(A_YYYY-1970) + (A_Yday+Floor((A_YYYY-1972)/4))*86400 + A_Hour*3600 + A_Min*60 + A_Sec
However, occasionally the result could be wrong: if a time update occurs during the evaluation of the expression, e.g. the A_Sec is 59 when it was used, but when the A_Min value is taken, Windows already incremented it. There are a number of ways to fix this. If AHK could stop the time update before the evaluation of the expression and resume it afterwards, it would be the cleanest solution. We could wait until A_Sec changes, and evaluate the long expression only after this. There should be no more change in the values for almost a second, enough to evaluate the expression:
Sec := A_Sec

L:

IfEqual A_Sec, %Sec%, GoTo L
But sometimes we still get wrong results (when Windows does something long in the background). A little longer code but safer solution is to take the whole time value at once, and extract the individual components. They don't change:
T = %A_Now%

FormatTime Y, T, yyyy

FormatTime D, T, YDay

FormatTime H, T, H

FormatTime M, T, m

FormatTime S, T, s

T := 31536000*(Y-1970) + (D+Floor((Y-1972)/4))*86400 + H*3600 + M*60 + S
Edit 20050816: added the reason why waiting for the Seconds to change is not bulletproof.

Mykron23
  • Guests
  • Last active:
  • Joined: --
Laszlo, sorry but I didn't understand one bit of that. Beginner..
Here is what I would like to do. I want to use the timestamp function code listed here and put it into an existing script I have. And the result of the timestamp to be output into a variable.

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
The 7 lines of the last script do just what you want: write the Unix time to the variable T. Test it, with MsgBox %T%. But the simplest solution is:
T = %A_Now%

T -= 19700101000000,seconds
These 2 lines do not have the update problem, either.

Mykron23
  • Guests
  • Last active:
  • Joined: --
I understand now. It seems to work good, thank you.

toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005

the simplest solution is:

T = %A_Now%
T -= 19700101000000,seconds
These 2 lines do not have the update problem, either.


Common, that is too simple. You take away all the fun. :)
That is too trivial and obvious for an AHK solution. It doesn't have the magic of hyperlinked GoTo statements with multiple encapsulated loops and if statements plus some BitwiseAnd and Xor. It's like taking a white rabit from a black zylinder and showing the crowd how you've done it.

That's what I call real problem solving. Nice work.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

kimballd
  • Members
  • 10 posts
  • Last active: Jan 24 2008 04:22 AM
  • Joined: 11 Jan 2005
Well toralf, here is that extra complication you were "looking" for:

A true Unix Timestamp is based off of Coordinated Universal Time (UTC) time (which is relatively close to Greenwich Mean Time (GMT)). Thus, the code could easily be edited to this:
T = %A_NowUTC% 
T -= 19700101000000,seconds
The complication comes when you try to interface with another program or system that calculates its own Unix Timestamps. Some will calculate it based off of its own time zone with or without daylight savings time, while others base it off of UTC. Watch out for these kinds variances.

mallick
  • Members
  • 2 posts
  • Last active: Jun 16 2006 09:06 PM
  • Joined: 16 Jun 2006
I love the code guys to go from human time to unix timestamp, by any chance anyone have the code handy to go from unix timestamp to human date/time output?

I the main reason I ask is I have a script that I am building that is doing some file work, but one of the fields in the file is a unix style timestamp and not sure how to convert it into human format.

Thanks for any examples/input/or ready made functions/scripts.

/bow

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
T = %A_Now% 

T -= 1970,s

MsgBox Unix Time = %T%



S = 1970

S += T,s

MsgBox YYYYMMDDHH24MISS = %S%