Search code examples
swiftapplescriptnsapplescriptnsappleeventdescriptor

How to pass date information to AppleScript?


I am making one app that can run AppleScript via NSAppleScript. Everything had been fine but I haven't been able to figure out how to pass date information from my app to AppleScript. (Since AppleScript has date type, I suppose this is possible) The way I pass parameters to AppleScript is through NSAppleEventDescriptor. I learned from Google that I could pass it as typeLongDateTime type:

- (id)initWithDate:(NSDate *)date {
     LongDateTime ldt;  
     UCConvertCFAbsoluteTimeToLongDateTime(CFDateGetAbsoluteTime((CFDateRef)date), &ldt);
     return [self initWithDescriptorType:typeLongDateTime
                                   bytes:&ldt
                                  length:sizeof(ldt)];
}

Unfortunately, the type LongDateTime had long gone, because I am using Swift and under OS X 10.10. Even the Core Services function UCConvertCFAbsoluteTimeToLongDateTime has already been removed from 10.10.3.

Now I am stuck.

Do you have any ideas that inspire?


Solution

  • Is seems that LongDateTime is a signed 64-bit integer which represents a date d as the number of seconds since January 1, 1904, GMT, adjusted by the time-zone offset for d in the local time zone (including daylight-savings time offset if DST is active at d).

    The following code gives the same result as your Objective-C code for all dates that I tested (winter time and summer time).

    class DateEventDescriptor : NSAppleEventDescriptor {
    
        convenience init?(date : NSDate) {
            let secondsSince2001 = Int64(date.timeIntervalSinceReferenceDate)
            var secondsSince1904 = secondsSince2001 + 3061152000
            secondsSince1904 += Int64(NSTimeZone.localTimeZone().secondsFromGMTForDate(date))
            self.init(descriptorType: DescType(typeLongDateTime),
                bytes: &secondsSince1904, length: sizeofValue(secondsSince1904))
        }
    }
    

    Update for Swift 3:

    class DateEventDescriptor : NSAppleEventDescriptor {
    
        convenience init?(date: Date) {
            let secondsSince2001 = Int64(date.timeIntervalSinceReferenceDate)
            var secondsSince1904 = secondsSince2001 + 3061152000
            secondsSince1904 += Int64(NSTimeZone.local.secondsFromGMT(for: date))
            self.init(descriptorType: DescType(typeLongDateTime),
                      bytes: &secondsSince1904, length: MemoryLayout.size(ofValue: secondsSince1904))
        }
    }
    

    Update for macOS 10.11:

    As of macOS 10.11 there is a

     NSAppleEventDescriptor(date: Date)
    

    initializer, so that the above workaround is no longer necessary. (Thanks to @Wevah for this information.)