Snow Leopard date conversion

I had this code in my pre-ASOC project. It got the time of the last reboot and then got the difference so I can display the time that has passed since the last reboot.

set lastReboot to date (do shell script "sysctl kern.boottime | awk '{print $12,$11,$14,$13}'")

tell (current date) - lastReboot
    set daysPassed to it div days
    set hoursPassed to it mod days div hours
    set minutesPassed to it mod hours div minutes
    set secondsPassed to it mod minutes
end tell

set my timeDateText to ("Time since last reboot: " & daysPassed & " Days, " & hoursPassed & " Hrs, " & minutesPassed & " Mins, " & secondsPassed & " Secs")

So, in Snow Leopard the first line is not working. From what I read here after searching, Snow Leopard is a lot more strict about the date format you give it if you try to convert a string to a date object. The weird thing when I ran tests in script editor I can’t seem to get anything to work:

set theDate to current date
--date "Monday, January 30, 2012 11:40:13 AM"

set theDateString to (current date) as string
--"Monday, January 30, 2012 11:40:33 AM"

set theDateAsDate to "Monday, January 30, 2012 11:40:33 AM" as date
--error "Can't make \"Monday, January 30, 2012 11:40:33 AM\" into type date." number -1700 from "Monday, January 30, 2012 11:40:33 AM" to date

What the heck?? I gave it the date string that it gave to me. Why would that be wrong??

Should I be switching over to NSDate? Is the above script easy to convert over?

Model: iMac
Browser: Firefox 3.6.4
Operating System: Mac OS X (10.6)

Well the biggest problem is that the notation settings in your system preferences is used to determine the correct date notation. For example in the US it is Month-Day-Year notation while the US notation is only 3% of the global date notations.

Because the project is ASOC I would use an NSDate object instead of AppleScript’s date object

Making dates from strings has become harder, but your sample script fails because you say:

set theDateAsDate to "Monday, January 30, 2012 11:40:33 AM" as date

rather than:

set theDateAsDate to date "Monday, January 30, 2012 11:40:33 AM"

However, even the latter won’t work in AppleScriptObjC. For reasons and suggested approaches, see:

www.macosxautomation.com/applescript/apps/gotchas.html

I am finding the NSTime thing to be completely incomprehensible…

Every example I find sets a new NSTime object to “current date”. I don’t want the current date, I want to create a string myself and then convert that. Can’t find any examples to do that.

I did make it work with all AppleScript after much cursing and gnashing of teeth…

--Get the last reboot time from shell scripts to create a date object
set theShortMonth to (do shell script "sysctl kern.boottime | awk '{print $11}'")
set theDay to (do shell script "sysctl kern.boottime | awk '{print $12}'") 
set theYear to (do shell script "sysctl kern.boottime | awk '{print $14}'")
set thetime to (do shell script "sysctl kern.boottime | awk '{print $13}'")
set theHour to text 1 thru 2 of thetime
set theMinutes to text 4 thru 5 of thetime
if theHour as integer > 11 then
    set amPm to "PM"
else
    set amPm to "AM"
end if
if (theHour as integer > 12) and (theHour as integer < 22) then
    set theHour to "0" & ((theHour as integer) - 12) as text
end if
if (theHour as integer > 21) then
    set theHour to ((theHour as integer) - 12) as text
end if
set theTimeFinal to theHour & ":" & theMinutes & ":00 " & amPm
set theDateString to theShortMonth & " " & theDay & ", " & theYear & " " & theTimeFinal
set lastReboot to current application's date theDateString as date
--Subtract the date object we created from the current date to get the time passed since the last reboot
tell (current date) - lastReboot
    set daysPassed to it div days
    set hoursPassed to it mod days div hours
    set minutesPassed to it mod hours div minutes
    set secondsPassed to it mod minutes
end tell
--Update property that is bound with text field on screen to display time since last reboot
set my timeDateText to ("Time since last reboot: " & (daysPassed as text) & " Days, " & (hoursPassed as text) & " Hrs, " & (minutesPassed as text) & " Mins, " & (secondsPassed as text) & " Secs")

I am trying not to vent but this conversion of my old projects has been painful so far. I knew certain things had to be rewritten, but I didn’t expect every single line of code to just totally not work. Basic lines of code that have worked for years like “set thisWholeFolder to conversionFolder as alias” are just not working. The editor/debugger are pretty terrible. It’s more or less trial and error trying to get anything to work.

But I said I wasn’t going to vent! Thanks for the help and advice. I am going to check out the link you posted and try the NSTime thing again.

Hi,

you can calculate time differences quite easy with NSDateComponents,
which provides access to each time/date part


set bootTime to text 1 thru -2 of (do shell script "sysctl kern.boottime | awk '{print $5}'")
set currentCalendar to current application's NSCalendar's currentCalendar()
set now to current application's NSDate's |date|()
set bootTimeDate to current application's NSDate's dateWithTimeIntervalSince1970_(bootTime) 
set unitFlags to 240 -- NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
set components to currentCalendar's components_fromDate_toDate_options_(unitFlags, bootTimeDate, now, 0)
set my timeDateText to ("Time since last reboot: " & (components's |day| as text) & " Days, " & (components's |hour| as text) & " Hrs, " & (components's |minute| as text) & " Mins, " & (components's |second| as text) & " Secs")

The normal way to get the boot time is the function

sysctlbyname("kern.boottime", &boottime, &length, NULL, 0);

but as ASOC doesn’t support C functions in Snow Leopard, the shell script works as well

Note: another advantage is the independency of any local date and time settings

Cool. Thanks for the example. That’s what I have been searching for but didn’t find.

That’s something you do with a date formatter. You need to set the date format, so it knows how you are going to give it a string to parse, then use dateFromString:

set df to current application's NSDateFormatter's alloc()'s init()
        df's setDateFormat_("MM/dd/yyyy HH:mm")
        log df's dateFromString_("11/06/2012 08:56")

This will give you an NSDate object. The log will still be in the standard format (2012-11-06 16:56:00 +0000), so you can use another formatter to format the output as well if you want to.

Ric