problem comparing dates

Hi

I need to work with dates in string format and later, to compare the dates, I convert to Date again but I’m getting this error:

Can’t make «script» into type string. (error -1700)

I’m using xcode 3.2

Here is a small code I made to test this:

script testdateAppDelegate
	
	on applicationWillFinishLaunching_(aNotification)
		set now to (current date) + 4 * hours
		-- convert to string
		set nowString to now as string
		-- and back to Date
		set newNow to date nowString
		if newNow > (current date) then -- I got the error here
			log ("greater than")
		end if
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return my NSTerminateNow
	end applicationShouldTerminate_
	
end script

Any help?

Gabo

It looks like forming dates from a string is broken in ASObjC – if you add “log class of NewNow” after “set newNow to date nowString”, you’ll see it’s returning a script object rather than a date. Log it as a bug.

Having said that, forming dates from strings is a pretty fragile business in 10.6; it fails if the format is not exactly right. Is there some reason you need to convert to and from text?

Thanks for your response, I better look another way.

Well yeah, I need to save the date into user defaults but in a previous test using setObject_forKey_ I can’t save the date directly, that is why i take the road to convert to string. I think that I need to look again over there.

Gabo

Of course you can

[i]Defaults are grouped in domains. Each domain has a name by which it’s identified and stores defaults as key-value pairs in an NSDictionary object. Each default is made up of three components:

The domain in which the default is stored
The name by which the default is identified (an NSString object)
The default’s value, which can be any property-list object (NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary)[/i]

The problem is that NSDate and AS dates aren’t interchangeable. If the OP can use NSDates from the start, there’ll be no problem, but if they need dates in AS, it will still be complicated.

Thanks for your responses. This make perfectly sense to me, I’m now changing my logic to use NSDate as my internal Date representation and use Shane’s code from another post to convert to AS Dates as needed to show in the user interface.

I will post the code when finish.

Regards
Gabo

again thanks to Shane and Stefan for the guidelines, here my final code:

script testdateAppDelegate
	property NSUserDefaults : class "NSUserDefaults" of current application
	
	on applicationWillFinishLaunching_(aNotification)
		set Expiration to readPrefs("Expiration")
		set now to current application's class "NSDate"'s |date|()
		if now's compare_(Expiration) is current application's NSOrderedDescending then
			set Expiration to now's dateByAddingTimeInterval_(4 * 60 * 60) --Expiration is 4 hour in the future
			savePref("Expiration", Expiration)
			log ("greater than" & ASDate(Expiration))
			-- Code when time expire
		else
			log ("Lower or equal")
			-- Code when not expire
		end if
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return my NSTerminateNow
	end applicationShouldTerminate_
	
	on ASDate(theDate)
		-- Created by Shane Stanley
		set theCal to current application's class "NSCalendar"'s currentCalendar()
		set theComponents to theCal's components_fromDate_(254, theDate)
		
		--The 254 is a mask for which components we want the result to contain; 254 means year, month, day, hour, minute, second, but there are others.
		
		--The NSDateComponents class has methods for extracting the components individually, so
		
		set theYear to theComponents's |year|()
		set theMonth to theComponents's |month|()
		set theDay to theComponents's |day|()
		set theHour to theComponents's hour()
		set theMinute to theComponents's minute()
		set theSecond to theComponents's |second|()
		
		--Now you need to make an AS date, and set the various components:
		
		set theDate to current date
		set day of theDate to 1 -- important
		set seconds of theDate to theSecond
		set year of theDate to theYear
		set month of theDate to theMonth
		set day of theDate to theDay
		set hours of theDate to theHour
		set minutes of theDate to theMinute
		return theDate as text
	end ASDate
	
	on savePref(thePrefName, thePrefValue)
		tell NSUserDefaults
			tell its standardUserDefaults()
				its setObject_forKey_(thePrefValue, thePrefName)
			end tell
		end tell
	end savePref
	
	on readPrefs(thePrefName)
		tell NSUserDefaults
			tell its standardUserDefaults()
				set returnPref to its objectForKey_(thePrefName)
			end tell
		end tell
		return returnPref
	end readPrefs
	
	
end script

You can also go from NSDate to AS date in fewer lines based on an approach Chris Nebel suggested:

set theDiff to theDate's timeIntervalSinceReferenceDate()
set ASDate to (date "Monday, January 1, 2001 12:00:00 AM") + theDiff div 1 + (time to GMT) -- date string will need to match your settings

That was buggy before 10.6.2 when run as 64-bit, but seems OK in 10.6.2.

The other thing probably worth mentioning is that you can, in a long-winded fashion, use the enumerations in the mask rather than “magic” numbers like 254. I’m not sure if this is something new in 10.6.2, or something I just missed in earlier versions. So this:

       set theComponents to theCal's components_fromDate_(254, theDate)

becomes something like:

		set theComponents to theCal's ¬
			components_fromDate_((current application's NSYearCalendarUnit as integer) ¬
				+ (current application's NSMonthCalendarUnit as integer) ¬
				+ (current application's NSDayCalendarUnit as integer) ¬
				+ (current application's NSHourCalendarUnit as integer) ¬
				+ (current application's NSMinuteCalendarUnit as integer) ¬
				+ (current application's NSSecondCalendarUnit as integer) ¬
				, theDate)

That’s a lot more typing, but it’s also much more readable code.

I see that approach too, but not used because the comment about 64-bit issue. Anyway the code is working so far and see pretty safe to me, so I will stay with the longer version.

Gabo

BTW the if clause is not working

       if now's compare_(Expiration) is current application's NSOrderedDescending then --Not Working
           set Expiration to now's dateByAddingTimeInterval_(4 * 60 * 60) --Expiration is 4 hour in the future
           savePref("Expiration", Expiration)
           log ("greater than" & ASDate(Expiration))
           -- Code when time expire

instead of current application’s NSOrderedDescending I write 1 then works, must be obvious but I don’t get it
EDIT: seem like is working on 10.6.2, tomorrow I’m going to check what version have on the macbook because there is where is not woking

Gabo

That would confirm my theory that this was something fixed in 10.6.2, along with the 64-bit date problems (and a couple of others).