Jump to content

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

Date parser - convert any date format to YYYYMMDDHH24MISS


  • Please log in to reply
85 replies to this topic
polyethene
  • Administrators
  • 5517 posts
  • Last active: Jun 02 2014 02:21 AM
  • Joined: 26 Oct 2012
This function converts almost any date format to a YYYYMMDDHH24MISS value.
Inspired by philz InvFormattime.

e.g. time := DateParse("2:35 PM, 27 November 2007")
It will also work with any of the following formats: 4:55 am Feb 27, 2004; 11:26 PM; 1532; 19/2/05; 2007-06-26T14:09:12Z.

Download

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Great work. I've linked to this topic from the FormatTime page. Its "Related" section now says, "To convert in the reverse direction -- that is, from a formatted date/time to YYYYMMDDHH24MISS format -- see <!-- m -->http://www.autohotke...topic20405.html<!-- m -->

polyethene
  • Administrators
  • 5517 posts
  • Last active: Jun 02 2014 02:21 AM
  • Joined: 26 Oct 2012
Thanks!

Ace_NoOne
  • Members
  • 299 posts
  • Last active: May 02 2008 08:19 AM
  • Joined: 10 Oct 2005
Impressive as usual, Titan!

However, I'm having trouble converting ISO 8601 timestamps:
t = 2007-06-25 13:15
MsgBox, % t . "`n" . DateParse(t)
This returns "20250607", though if I'm not mistaken, it should return "20070625131500"!?

Conceptual question: Wouldn't it be easier (or more reliable and flexible) if the function call included the input string's date format? So in my case, I'd just use "DateParse(yyyy-MM-dd HH:mm)" and be done with it.
Though there is (or will be) philz's InvFormattime for that...

polyethene
  • Administrators
  • 5517 posts
  • Last active: Jun 02 2014 02:21 AM
  • Joined: 26 Oct 2012
Oh right, I forgot that T is an optional flag. Fixed in 1.01 thanks.

Wouldn't it be easier (or more reliable and flexible) if the function call included the input string's date format?

Well so long as you use a standard format (UK/US locale or ISO for international) this function should be able to convert it.

philz
  • Members
  • 89 posts
  • Last active: Mar 02 2009 06:23 AM
  • Joined: 05 Jun 2007

Conceptual question: Wouldn't it be easier (or more reliable and flexible) if the function call included the input string's date format? So in my case, I'd just use "DateParse(yyyy-MM-dd HH:mm)" and be done with it.
Though there is (or will be) philz's InvFormattime for that...


I agree with you're point. i really like titan's use of regexes, (i just started dallying with them myself and MAN they're useful) but i like the ability to work with the rediculous times i mention in the invformattime() disgussion. i had my high school graduation party this weekand and i couldn't work on it. sry Until i include a more convenient time format entry parameter, you can add the "-" to the list of delimiters in my script to get the iso timestamps converted

Ace_NoOne
  • Members
  • 299 posts
  • Last active: May 02 2008 08:19 AM
  • Joined: 10 Oct 2005

Oh right, I forgot that T is an optional flag. Fixed in 1.01 thanks.

Hm, I thought I had tried it with the T flag as well... :?

so long as you use a standard format (UK/US locale or ISO for international) this function should be able to convert it

Yeah, but kinda like philz, I'm always thinking "What if aliens invade earth and force us all to use their crazy timestamp format?"
(Meaning: Hard-coding formats - even if they're standardized - is not flexible, and thus not future-proof.)
That's just my twisted mind though...

Anyway, here's a non-philosophical issue:
Since I've implemented DateParse(), I'm having trouble with my calculations.
Here's a simplified version of my code:
startDate := DateParse("2007-06-25 18:52")
endDate := DateParse("2007-06-26 09:23")
GoSub, calcProgress
Return

; calculate current progress
calcProgress:
	; total time
	totalTime := endDate
	totalTime -= startDate, Seconds
	totalTime_days := totalTime / (60 * 60 * 24)
	; time elapsed/left
	currentDate := A_Now
	timeElapsed := currentDate
	timeElapsed -= startDate, Seconds
	timeElapsed_days := timeElapsed / (60 * 60 * 24)
	timeLeft := totalTime - timeElapsed
	timeLeft_days := timeLeft / (60 * 60 * 24)
	; current progress
	currentProgress := timeElapsed / totalTime * 100
	MsgBox, total: %totalTime%`ntotal days: %totalTime%`nelapsed: %timeElapsed%`nelapsed days: %timeElapsed%`nleft: %timeLeft%`nleft days: %timeLeft_days%`nprogress: %currentProgress%
Return
For some reason, currentProgress takes on the value "D." (it was "D.f." in previous attempts IIRC).
I have checked and reviewed that code many, many times - but I just can't figure out what the problem is. On the one hand, DateParse() seems to return the correct data, but there's nothing else that might cause this sudden problem!?
Maybe it's just me being tired, plus I hate time calculations anyway - but I'm out of ideas here, so I'd greatly appreciate some support!

engunneer
  • Moderators
  • 9162 posts
  • Last active: Jul 15 2014 12:00 AM
  • Joined: 30 Aug 2005
totalTime_days is coming out D. first.

If I do this in a new script, I get the right number:
   totalTime = 52260
   totalTime_days := totalTime / (60 * 60 * 24)
   MsgBox, %totalTime%  %totalTime_days%

If It do it to your script, I get D.

startDate := DateParse("2007-06-25 18:52")
endDate := DateParse("2007-06-26 09:23")
GoSub, calcProgress
Return

; calculate current progress
calcProgress:
   ; total time
   totalTime := endDate
   totalTime -= startDate, Seconds
   totalTime = 52260   ;for testing!
   totalTime_days := totalTime / (60 * 60 * 24)
   MsgBox, %totalTime%  %totalTime_days%
   ; time elapsed/left
   currentDate := A_Now
   timeElapsed := currentDate
   timeElapsed -= startDate, Seconds
   timeElapsed_days := timeElapsed / (60 * 60 * 24)
   timeLeft := totalTime - timeElapsed
   timeLeft_days := timeLeft / (60 * 60 * 24)
   ; current progress
   currentProgress := timeElapsed / totalTime * 100
   listvars
   pause
   MsgBox, %currentProgress%
Return



/*
	Title: Date Parser
	
	Function: DateParse
	
	Converts almost any date format to a YYYYMMDDHH24MISS value.
	
	Parameters:
		str - a date/time stamp as a string
	
	Returns:
		A valid YYYYMMDDHH24MISS value which can be used by FormatTime,
		EnvAdd and other time commands.
	
	About: Example
		- time := DateParse("2:35 PM, 27 November, 2007")
	
	About: License
		- Version 1.01 by Titan <http://www.autohotkey.net/~Titan/#dateparse>.
		- Licenced under GNU GPL <http://creativecommons.org/licenses/GPL/2.0/>.

*/

DateParse(str) {
	static e1 = "i)(\d{1,2})\s*:\s*(\d{1,2})(?:\s*(\d{1,2}))?\s*([ap]m)"
		, e2 = "i)(?:(\d{1,2}+)[\s\.\-\/,]+)?(\d{1,2}|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\w*)[\s\.\-\/,]+(\d{2,4})"
	str := RegExReplace(str, "((?:" . SubStr(e2, 42, 47) . ")\w*)(\s*)(\d{1,2})\b", "$3$2$1", "", 1)
	If RegExMatch(str, "i)^\s*(?:(\d{4})([\s\-:\/])(\d{1,2})\2(\d{1,2}))?"
		. "(?:\s*[T\s](\d{1,2})([\s\-:\/])(\d{1,2})(?:\6(\d{1,2})\s*(?:(Z)|(\+|\-)?"
		. "(\d{1,2})\6(\d{1,2})(?:\6(\d{1,2}))?)?)?)?\s*$", i)
		d3 := i1, d2 := i3, d1 := i4, t1 := i5, t2 := i7, t3 := i8
	Else If !RegExMatch(str, "^\W*(\d{1,2}+)(\d{2})\W*$", t)
		RegExMatch(str, e1, t), RegExMatch(str, e2, d)
	f = %A_FormatInteger%
	SetFormat, Float, 02.0
	d := (d3 ? (StrLen(d3) = 2 ? 20 : "") . d3 : A_YYYY)
		. ((d2 := d2 + 0 ? d2 : (InStr(e2, SubStr(d2, 1, 3)) - 40) // 4 + 1.0) > 0 ? d2 + 0.0 : A_MM)
		. ((d1 += 0.0) ? d1 : A_DD) . t1 + (t4 = "pm" ? 12.0 : 0.0) . t2 + 0.0 . t3 + 0.0
	SetFormat, Float, %f%
	Return, d
}



Ace_NoOne
  • Members
  • 299 posts
  • Last active: May 02 2008 08:19 AM
  • Joined: 10 Oct 2005
This is a complete mystery to me - I've updated the test script above to display all relevant variables. However, that doesn't help me in figuring out what the problem is... :(

enguneer: The difference between your script and mine is that I have used DateParse() - corroborating my suspicion that it must have something to do with Titan's function!?

polyethene
  • Administrators
  • 5517 posts
  • Last active: Jun 02 2014 02:21 AM
  • Joined: 26 Oct 2012

I thought I had tried it with the T flag as well...

The old version required the seconds to be present as well which I forgot to mention sorry.

"What if aliens invade earth and force us all to use their crazy timestamp format?"
(Meaning: Hard-coding formats - even if they're standardized - is not flexible, and thus not future-proof.)

Antithesis: the thousands of programs/databases/websites designed with ECMAScript will also break
Synthesis: if you use the universally accepted ISO 8601 format compatibility shouldn't be a concern

How's your theology studies coming on btw ;)

For some reason, currentProgress takes on the value "D."

My bad, I was using A_FormatInteger when it should be A_FormatFloat. Fixed in 1.02, thanks again and cheers to engunneer as well.

Ace_NoOne
  • Members
  • 299 posts
  • Last active: May 02 2008 08:19 AM
  • Joined: 10 Oct 2005

Antithesis: the thousands of programs/databases/websites designed with ECMAScript will also break
Synthesis: if you use the universally accepted ISO 8601 format compatibility shouldn't be a concern

Nice argumentation.
I guess I can live with that synthesis (I'm always using ISO 8601 anyway) - though I still think philz's version has a raison d'ĂȘtre.

UPDATE:
I just realized when Titan's approach might be superior (cf. this posting): As soon as there's user interaction, Titan's DateParse function will enable the user to choose from a wide variety of timestamp formats. In contrast, philz's InvFormattime is more flexible for the programmer, though not for the end user.

My bad, I was using A_FormatInteger when it should be A_FormatFloat.

No problem; I'll send you the bill for the hours I've wasted doubting myself, as well as for the time I've spent on the Shrink Hotline. ;)
Thanks for the quick response, Titan - it works perfectly now!

[OT]
My theology studies, eh? I'm still an agnostic, if that's what you mean... :p
The studies are coming along nicely; I'll be done soon(ish) - and ready to join the Real World.
For more information, visit irc://irc.freenode.net/autohotkey...
[/OT]

EdScriptNewbie
  • Members
  • 117 posts
  • Last active: Aug 19 2013 07:32 PM
  • Joined: 20 Jan 2007
I hope it's ok that I put this here; somehow if I understood any of this thread about dates I probably would not need to ask this at all.
I want to select the date field in an Outlook Task, collect the date (into a variable?), then add to or subtract from that date a certain number of days, and then, write the resulting new date into the field in a format it can use. The Outlook Task date field is in this format: "Wed 6/27/2007."
The following might make this easier:
1) the day name part of it is always three letters followed by a space, and
2) if you select the whole field and just paste in 6/28/2007, then when you tab onward, Outlook in its wisdom figures out how to make the field say "Thu 6/28/2007" all by itself.

Ace_NoOne
  • Members
  • 299 posts
  • Last active: May 02 2008 08:19 AM
  • Joined: 10 Oct 2005
EdScriptNewbie: Although you didn't really pose a question, I guess DateParse() will do what you need.
date := DateParse("Wed 6/27/2007")
This will make the date variable a YYYYMMDDHH24MISS timestamp which you can work with.
For information on time calculations, see EnvAdd and EnvSub (that's stuff for another thread though).

btw Titan: What's the licensing for this function - does the entire header comment need to stay intact, or is there a smaller version? Just curious...

polyethene
  • Administrators
  • 5517 posts
  • Last active: Jun 02 2014 02:21 AM
  • Joined: 26 Oct 2012
EdScriptNewbie, like Ace_NoOne demonstrated you can convert the string to an AutoHotkey compatible format using this function, add/subtract a number of days using EnvAdd/EnvSub, convert it back to the original date format using FormatTime and then send it back to Outlook with Send or ControlSend.

The script can be modified/distributed however you want as long as it includes the original version number, link to my site and a notice of GPL v2 - AutoHotkey comes with this licence so linking to a GNU site is not necessary, e.g.

DateParse(str) { ; v1.02 http://www.autohotkey.net/~Titan/#dateparse - GPL v2


EdScriptNewbie
  • Members
  • 117 posts
  • Last active: Aug 19 2013 07:32 PM
  • Joined: 20 Jan 2007
My thanks to you both. Titan, thanks too for having contributed that; I'll be sure to put the license stuff you mentioned in my script. Thanks again!