Explanation requested - coercion of text into date

As a somewhat novice Applescripter, I’m confused by why coercion of text to date works in some contexts and not in others. For example, this script generates an error:


tell application "AppleScript Editor"
	set theText to "04/15/2012"
	set theDate to date theText 
end tell

But if I leave off the tell block, the script works:


set theText to "04/15/2012"
set theDate to date theText 

If I put the coercion line from the first script in handler, that makes it work:

tell application "AppleScript Editor"
	set theText to "04/15/2012"
	set theDate to my DateFromText(theText)
	return theDate
end tell

on DateFromText(theText)
	return date theText
end DateFromText

This variation on the first script also generates and error:

tell application "AppleScript Editor"
	set theText to "04/15/2012"
	set theDate to theText as date
end tell

However, this variation with “double coercion” works:

tell application "AppleScript Editor"
	set theText to "04/15/2012"
	set theDate to date theText as date
end tell

If anyone can explain to me why some of these work and others don’t, it would be greatly appreciated.

Thanks!

Hi,

AppleScript Editor is the tool to create and manage scripts, it’s not the runtime environment.
An application tell block is required (at compile time) to indicate that specific terminology of this application is used.

date is a basic AppleScript type, which works best without any tell block

AppleScript has become much more strict in what it considers to be a valid date - so coercion of text to date has become somewhat more of a hassle. It is now considered “good scripting” to start with ‘current date’, and set its properties to get to the date you need.
Sample code:

tell (current date) to set {thisDate, its day, its month, its year, its time} to {it, 15, 5, 2007, (9 * hours + 15 * minutes)}

Leave out properties you do not need.
As a (very desirable!) side effect your script will be timeformat/zone/DST-agnostic: it will work anywhere, anytime without modification.

When modifying a date object this way, overflow can occur if the target date’s incompatible with the start date in terms of days per month. For instance, today’s 2nd April 2012 and I want to create 31st May 2007:

tell (current date) to set {thisDate, its day, its month, its year, its time} to {it, 31, 5, 2007, (9 * hours + 15 * minutes)}
thisDate -- date "Tuesday 1 May 2007 09:15:00"

Setting a 30-day month’s day to 31 causes it to overflow to the 1st of the following month, which makes the day wrong for the rest of the process. A similar thing happens when start date’s day is, say, 31 and its month is changed to one with less than that number of days. The amount of the overflow depends on the month and day set.

To avoid this, it’s best first to set the day to one which occurs in every month of the year (1 is a good choice for clarity), then set the month and the year (or the year and the month), and then set the day to the required value:

tell (current date) to set {thisDate, its day, its month, its year, its day, its time} to {it, 1, 5, 2007, 31, (9 * hours + 15 * minutes)}
thisDate -- date "Thursday 31 May 2007 09:15:00"

All good info, thanks!

However, what I’m actually trying to accomplish is to convert date text into date object in the case where I know the date text conforms to the system date formats, but I have no idea what date format will be input until runtime:

set myDates to {"11/5/12", "11/05/2012", "Nov 5 2012", "Nov 5, 2012", "Thu, Nov 5, 2012", "November 5, 2012"}
set newDates to {}
repeat with theText in myDates
	set theDate to date theText
	set end of newDates to theDate
end repeat

return newDates -- {date "Mon, November 5, 2012 00:00:00 ", date "Mon, November 5, 2012 00:00:00 ", date "Mon, November 5, 2012 00:00:00 ", date "Mon, November 5, 2012 00:00:00 ", date "Mon, November 5, 2012 00:00:00 ", date "Mon, November 5, 2012 00:00:00 "}

I realize I could write a (somewhat humongous) regular expression to handle all the possible date text formats, but was trying to avoid that pain. I discovered that the system date coercion will work for me, but only in certain context. Was just trying to get a better understanding of why/how the context matters.

If anyone has an already written routine to handle conversion of text dates in a wide variety of formats, that would be great!

R

If you know that the likely inputs will match the preferences on the system, you may as well use a date specifier ” ie. ‘date’ + text variable ” to create the date objects and let AppleScript do the hard work for you. You just have to remember that making a date object from a date specifier is something that vanilla AppleScript knows how to do and most applications don’t, so putting the specifier inside an application ‘tell’ statement can lead to failure.

The tell-block problem seems to be particularly bad with date specifiers. (Alias or file specifiers are usually OK, for instance.) I think there’s possibly some terminology clash which makes applications think the ‘date’ thing is for them, so they try to handle it themselves instead of leaving it to AppleScript proper.

The absolute best thing is not to put a date specifier inside an application ‘tell’ statement, but there are ways to neutralise the context momentarily if it can’t be avoided.


tell application "AppleScript Editor"
	set theText to "1/1/2012"
	
	tell me to set theDate to date theText
	-- Or:
	set theDate to my date theText
	-- Or:
	set theDate to AppleScript's date theText
end tell

Thanks. I like the last one for its clarity and I’ll use it. Cleaner than a silly one-line handler outside the application tell block.

R