Archive for the 'NSCalendar' Category

2017/11/20 主要なタイムゾーンのカレンダーの開始曜日を取得して集計

macOS内に定義されているタイムゾーン(knownTimeZoneNames)のカレンダーの開始曜日を取得して、firstWeekdayを集計するAppleScriptです。

取得するScriptに集計部分を追加しただけのものです。

AppleScript名:主要なタイムゾーンのカレンダーの開始曜日を取得して集計
– Created 2017-11-15 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
–http://piyocast.com/as/archives/4990

property NSDate : a reference to current application’s NSDate
property NSCalendar : a reference to current application’s NSCalendar
property NSOrderedSet : a reference to current application’s NSOrderedSet
property NSLocale : a reference to current application’s NSLocale
property NSCountedSet : a reference to current application’s NSCountedSet
property NSMutableArray : a reference to current application’s NSMutableArray
property NSTimeZone : a reference to current application’s NSTimeZone

set currentCalendar to NSCalendar’s currentCalendar()
set tzList to (NSTimeZone’s knownTimeZoneNames()) as list

set fList to {}
repeat with i in tzList
  set j to contents of i
  (
currentCalendar’s setLocale:(NSLocale’s localeWithLocaleIdentifier:j))
  
  
set aTZ to (NSTimeZone’s timeZoneWithName:j)
  
set theComponents to (currentCalendar’s componentsInTimeZone:aTZ fromDate:(NSDate’s |date|()))
  
set tmpCalend to theComponents’s calendar()
  
  
set aFirstDay to (tmpCalend’s firstWeekday) as integer –firstWeekday: 1=Sunday, 2=Monday
  
set the end of fList to aFirstDay
end repeat

set aRes to calcFrequency(fList) of me
–> {{theKey:1, theCount:371}, {theKey:2, theCount:66}}

–1D Listのデータを各要素ごとに出現頻度集計
on calcFrequency(fList)
  set f2List to makeUniqueListFrom(fList) of me
  
  
set theCountedSet to NSCountedSet’s alloc()’s initWithArray:fList
  
set newArray to NSMutableArray’s new()
  
repeat with i in f2List
    (newArray’s addObject:{theKey:i, theCount:(theCountedSet’s countForObject:i)})
  end repeat
  
return newArray as list
end calcFrequency

–リスト内容のユニーク化
on makeUniqueListFrom(theList)
  set theSet to NSOrderedSet’s orderedSetWithArray:theList
  
return (theSet’s array()) as list
end makeUniqueListFrom

★Click Here to Open This Script 

2017/11/20 主要なタイムゾーンのカレンダーの開始曜日を取得

macOS内に定義されているタイムゾーン(knownTimeZoneNames)のカレンダーの開始曜日を取得するAppleScriptです。

macOS内に定義されているタイムゾーンは437あり、当然のことながら時差は±12h(24のタイムゾーン)しかないので、それぞれのタイムゾーンの「時差」は重複しています。

どちらかといえば、各国が採用しているカレンダーの仕様(どの曜日からはじまるか)を調べるために書いてみたものです。各国の首都が所在しているタイムゾーンを求め、そこのカレンダーの仕様を調べられるとよかったのですが、OS内部のAPIだけでは実現できなかったので、かわりに「knownTimeZoneNames」を呼び出してみた次第です。

週の開始日を示すfirstWeekdayは1:Sunday, 2:Monday….となっており、多くのT imezoneがSundayであることが見てとれます。

自分が位置しているタイムゾーン「Asia/Tokyo」は2(=Monday)とありました。

ただし、実際にシステム環境設定で「言語と地域」をオープンしてみると、

system_resized.png

日曜日(Sunday)。個人的にも日曜日はじまりで違和感がありません。はて?

ちなみに、1週間の開始曜日は海外のクライアントと仕事をするうえで、(日本の日常会話における)天気の話なみに重要な項目です。「常識」が常識ではないことの確認を行うことは重要です。

AppleScript名:主要なタイムゾーンのカレンダーの開始曜日を取得
– Created 2017-11-14 by Takaaki Naganoya
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4988

set currentCalendar to current application’s NSCalendar’s currentCalendar()
set knownTimeZoneNameList to current application’s NSTimeZone’s knownTimeZoneNames() as list

set fList to {}
repeat with i in knownTimeZoneNameList
  set j to contents of i
  (
currentCalendar’s setLocale:(current application’s NSLocale’s localeWithLocaleIdentifier:j))
  
  
set aTZ to (current application’s NSTimeZone’s timeZoneWithName:j)
  
set theComponents to (currentCalendar’s componentsInTimeZone:aTZ fromDate:(current application’s NSDate’s |date|()))
  
set tmpCalend to theComponents’s calendar()
  
set aFirstDay to (tmpCalend’s firstWeekday) as integer
  
set the end of fList to aFirstDay
end repeat

return fList –firstWeekday: 1=Sunday, 2=Monday

★Click Here to Open This Script 

2017/09/23 指定日時以降に作成されたファイルをSpotlight検索 v3

指定フォルダ(Desktop)以下のファイルで、指定日時以降に作成されたものをSpotlight検索するAppleScriptの修正版です。

Metadata Libの作者であるShane Stanleyから直接「こうしたほうがいいよ」と教えてもらいました。たしかに、dateをイチイチISO8601日付文字列に変換しないといけないというのは、さすがにおかしいと思っていました(汗)。

記述と処理がシンプルになっただけで、v2でもv3でも処理時間に大差はありません。同じ対象に対して同じ検索を行なって、0.01秒弱というところでした。

本ルーチンでは指定年月日でNSDateオブジェクトを生成し、それをもとにMetadata LibでSpotlight検索を行なっています。実行のさいには、Metadata Libを~/Library/Script Libraries/フォルダに入れておく必要があります。

従来、自分はAppleのMailing ListやWebフォーラムなどの情報、および海外で販売されていたAppleScript CD-ROMなどを購入するなどして、ほぼ一方的に英語ベースの情報を受け身で収集していたわけですが、このようなBlogによる情報発信やらGoogle翻訳の精度向上の影響で、割と些細な情報も相互に伝わるようになりつつある昨今です。

AppleScript名:指定日時以降に作成されたファイルをSpotlight検索 v3
– Created 2017-09-21 by Takaaki Naganoya
– Modified 2017-09-22 by Shane Stanley
– 2017 Piyomaru Software
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”
use mdLib : script “Metadata Lib” version “1.0.0″
–http://piyocast.com/as/archives/4841

property NSTimeZone : a reference to current application’s NSTimeZone
property NSCalendar : a reference to current application’s NSCalendar

set aDate to getDateInternationalYMDhms(2017, 9, 21, 23, 2, 0) of me
–>  (NSDate) 2017-09-21 14:02:00 +0000

set thePath to POSIX path of (path to desktop)
–>  ”/Users/me/Desktop/”

set theFiles to mdLib’s searchFolders:{thePath} searchString:(“kMDItemFSCreationDate >= %@”) searchArgs:{aDate}
–> returns POSIX path list

on getDateInternationalYMDhms(aYear, aMonth, aDay, anHour, aMinute, aSecond)
  set theNSCalendar to NSCalendar’s currentCalendar()
  
set theDate to theNSCalendar’s dateWithEra:1 |year|:aYear |month|:aMonth |day|:aDay hour:anHour minute:aMinute |second|:aSecond nanosecond:0
  
return theDate
end getDateInternationalYMDhms

★Click Here to Open This Script 

2017/09/22 指定日時以降に作成されたファイルをSpotlight検索 v2

指定フォルダ(Desktop)以下のファイルで、指定日時以降に作成されたものをSpotlight検索するAppleScriptです。

本ルーチンの原型は、電子書籍を作成する際にMarkdown書類(MacDown)とPages書類をまとめてPDFに出力して1つのPDFに連結するAppleScriptで使っていたものです(こういう武器がないと、電子書籍を執筆からレイアウトから何から何までひとりで行うことなんてできません)。

bookfiles2.png
Pagesはともかく、MacDownからは指定フォルダにPDFを書き出すという機能は(MacDownのAppleScript用語辞書に機能が用意されていないため)AppleScriptからは利用できませんでした。そこで、GUI Scriptingで強引にデスクトップにPDF書き出しすることに。

デスクトップに書き出させたのは、保存ダイアログ上でCommand-Dのキーボードショートカットで一意に指定できる数少ないフォルダだからです(このあたり、生活の知恵)。

GUI Scriptingでファイル保存やファイル書き出しを行う場合、保存ダイアログがどこのフォルダを指し示すかはアプリケーション側まかせなので、保存/書き出し先フォルダをデスクトップに強引に指定する処理はたいへん重要です。GUI Scriptingはたいへんに弱点が多く不確実な手段ですが、不確実さを地道につぶしてあげることで、信頼性のある処理フローを構築できます。

PDF書き出し開始時のタイムスタンプを変数に記憶させておき、その時刻以降でデスクトップに生成されたPDFをすべて取得し、ファイル名でソート(ファイル名の先頭にソート用の仮想ノンブルをつけて管理)し、(末尾に生じていた意図しない空白ページ自動削除しつつ)1つのPDFに合成していました。

そのため、日時を指定して指定フォルダに存在するファイルをSpotlight検索する本ルーチンの重要度はとても高かったわけです。

当初は日付情報をJan 1 2001 00:00:00 GMTからの相対秒(Absolute Time)で指定していたのですが、OSのバージョンアップにともないこの書き方が使えなくなったため、仕方なく対処。

本ルーチンでは指定年月日でdateオブジェクトを生成したあと、ISO8601形式の日付文字列に変換し、それをもとにShane StanleyのMetadata LibでSpotlight検索を行なっています。実行のさいには、Metadata Libを~/Library/Script Libraries/フォルダに入れておく必要があります。

AppleScript名:指定日時以降に作成されたファイルをSpotlight検索 v2
– Created 2017-09-21 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.5″
use framework “Foundation”
use scripting additions
use mdLib : script “Metadata Lib” version “1.0.0″
–http://piyocast.com/as/archives/4838

property NSTimeZone : a reference to current application’s NSTimeZone
property NSCalendar : a reference to current application’s NSCalendar
property NSDateFormatter : a reference to current application’s NSDateFormatter

set aDate to getDateInternationalYMDhms(2017, 9, 21, 23, 2, 0) of me
–>  date “2017年9月21日木曜日 23:02:00″

set bStr to retISO8601DateTimeString(aDate) as string
–>  ”2017-09-21T14:02:00Z”

set thePath to POSIX path of (path to desktop)

set theFiles to mdLib’s searchFolders:{thePath} searchString:(“kMDItemFSCreationDate >= ’$time.iso(\”" & bStr & “\”)’”) searchArgs:{}
–> returns POSIX path list

–NSDate -> ISO8601 Date & Time String
on retISO8601DateTimeString(targDate)
  set theNSDateFormatter to NSDateFormatter’s alloc()’s init()
  
theNSDateFormatter’s setDateFormat:“yyyy-MM-dd’T’HH:mm:ss’Z’”
  
theNSDateFormatter’s setTimeZone:(NSTimeZone’s alloc()’s initWithName:“UTC”)
  
return (theNSDateFormatter’s stringFromDate:targDate) as text
end retISO8601DateTimeString

–現在のカレンダーで指定年月のdate objectを返す(年、月、日、時、分、秒)
on getDateInternationalYMDhms(aYear, aMonth, aDay, anHour, aMinute, aSecond)
  set theNSCalendar to NSCalendar’s currentCalendar()
  
set theDate to theNSCalendar’s dateWithEra:1 |year|:aYear |month|:aMonth |day|:aDay hour:anHour minute:aMinute |second|:aSecond nanosecond:0
  
return theDate as date
end getDateInternationalYMDhms

★Click Here to Open This Script 

2016/02/10 ISO8601ちっくな週カウント

Cocoaの機能を用いて指定日付が1年のうちの何週目にあたるか、一般常識的なカウントと、ISO8601で規定されている週カウントの両方で計算するAppleScriptです。

iso8601wc.png

ISO8601で規定している週番号では、1/1が木曜日から土曜日までの間にある場合には前年の12月の最終週の続きとして扱われます。aWNがiCalの画面上に表示される週番号、bWNがISO8601に則ってカウントした週番号です。

AppleScript名:ISO8601ちっくな週カウント
– Created 2016-02-10 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aNSDate to makeNSDate(2016, 1, 1) of me
set aCal to current application’s NSCalendar’s currentCalendar()
aCal’s setMinimumDaysInFirstWeek:1
set aWN to (aCal’s components:(current application’s NSWeekCalendarUnit) fromDate:aNSDate)’s week()

aCal’s setMinimumDaysInFirstWeek:4 –ISO8601 Week Count
set bWN to (aCal’s components:(current application’s NSWeekCalendarUnit) fromDate:aNSDate)’s week()

return {aWN, bWN}
–>  {1, 52}

–Y,M,Dを指定してNSDateを作成
on makeNSDate(aYear as integer, aMonth as integer, aDay as integer)
  set aComp to current application’s NSDateComponents’s alloc()’s init()
  
aComp’s setDay:aDay
  
aComp’s setMonth:aMonth
  
aComp’s setYear:aYear
  
set aGrego to current application’s NSCalendar’s calendarWithIdentifier:(current application’s NSGregorianCalendar)
  
set aDate to aGrego’s dateFromComponents:aComp
  
return aDate
end makeNSDate

★Click Here to Open This Script 

2015/08/27 100%クラッシュするNSCalendarの操作

AppleScriptObjCでNSCalendarをテストしだしたところ、実行するScript Editorが100%クラッシュする記述に遭遇。OS X 10.10.5でも、OS X 10.11 Betaでもクラッシュします(バグレポートずみ)。

# OS X 10.10.x/10.11.xでこれを実行してクラッシュしない環境があったら、逆におしえていただきたいです(2台でともに100%クラッシュ)

MacScriptersのBBSでもクラッシュの話が(ずいぶん前から)出ており、有名な話のようです。

*** CAUTION: THIS SCRIPT CAUSE CRASH ***

AppleScript名:ASOCでNSCalendarのじっけん(100%クラッシュ)
– Created 2015-08-27 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aCal to current application’s NSCalendar’s alloc()’s initWithCalendarIdentifier:(current application’s NSGregorianCalendar)

★Click Here to Open This Script 

Shane Stanleyから「こう書くとクラッシュを避けられるよ」というのを教えてもらいました。本当に重要ですよね、落とし穴がどこにあいているかの情報は、、、

AppleScript名:クラッシュしないNSCalendarのじっけん
– Created 2015-08-28 by Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aCal to current application’s NSCalendar’s calendarWithIdentifier:(current application’s NSGregorianCalendar)
–>  (_NSCopyOnWriteCalendarWrapper) <_nscopyonwritecalendarwrapper : 0x610000239e20>

★Click Here to Open This Script 

2015/02/25 Conversion between UTCTime String and NSDate

Conversion ASOC script between UTCTime String (with milli-seconds) and NSDate.

In US Apple’s AppleScript Users ML, I saw the thread “UTC time with milliseconds”.

They talk about only current date -> UTCTime string (with milli-seconds) . And there is no care of each time zone.

So, I added time zone consideration and reverse conversion handler.

Reverse conversion (UTCTime string -> NSDate) does not need to get users time zone, I think.

Ole Begemann’s Working with Date and Time in Cocoa was very useful and helpful for me.

Shane Stanley taught me this is not right. Oh! my Buddha! (something like God..)

I misunderstood the definition of the word “UTCTime”. I meant it as a time string. So, I’ll fix this later. Hmm..I don’t need to get “UTCTime” string….Is there any need to get it?

AppleScript名:UTCTime StringとNSDateの相互変換
– Created 2015-02-24 by Shane Stanley
– Changed 2015-02-25 By Takaaki Naganoya
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aStr to retUTCTimeString()
–>   “2015-02-25T13:49:55.713″

set aNSDate to retNSDateFromUTCString(aStr)
–>  (NSDate) 2015-02-25 13:49:55 +0000 –ASObjC Explorer
–> «class ocid» id «data optr0000000030F7400000600000» –Apple’s Script Editor

–Current Date -> UTCTime String
on retUTCTimeString()
  –There is need to get Current Calendar in my Time Zone
  
set aCalendar to current application’s NSCalendar’s currentCalendar()
  
set aTimeZone to (aCalendar’s timeZone)
  
set tDiff to (aTimeZone’s secondsFromGMT())
  
  
set theNSDateFormatter to current application’s NSDateFormatter’s alloc()’s init()
  
  
theNSDateFormatter’s setDateFormat:“yyyy-MM-dd’T’HH:mm:ss.SSS”
  
theNSDateFormatter’s setTimeZone:(current application’s NSTimeZone’s timeZoneForSecondsFromGMT:tDiff)
  
  
return (theNSDateFormatter’s stringFromDate:(current application’s NSDate’s |date|())) as text
end retUTCTimeString

–UTCTime String -> NSDate
on retNSDateFromUTCString(aText)
  set aStr to current application’s NSString’s stringWithString:aText
  
  
set theNSDateFormatter to current application’s NSDateFormatter’s alloc()’s init()
  
theNSDateFormatter’s setDateFormat:“yyyy-MM-dd’T’HH:mm:ss.SSS”
  
theNSDateFormatter’s setTimeZone:(current application’s NSTimeZone’s timeZoneForSecondsFromGMT:0)
  
  
return theNSDateFormatter’s dateFromString:aStr
end retNSDateFromUTCString

★Click Here to Open This Script 

2015/02/02 2月1日が日曜日でうるう年ではないかチェック(ASOC)

先日の「2月1日が日曜日でうるう年ではない(1日から28日までびっしり数字が入っている)」年を検出する(技術の無駄遣い的な ^ー^;)AppleScriptのASOC版です。Shane Stanleyが送ってくれました(こんなくだらないScriptに付き合わせて申し訳ない、、、)。

3,000年分計算して、だいたい0.8秒ぐらい。Pure AppleScript版より2倍以上高速ですが、3,000年程度の計算ではASOCの真の力が発揮できません。

AppleScript名:2月1日が日曜日でうるう年ではないかチェック(ASOC)
– Created 2015-02-02 by Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”

set resYList to {} –hit year

set theNSCalendar to current application’s NSCalendar’s currentCalendar() – do *not* use initWithCalendarIdentifier:

repeat with y from 0 to 3000
  set aMlen to getMlenAndVerifyFirstDaysNum(y, 2, theNSCalendar, 28, 1) of me
  
if aMlen = true then
    set the end of resYList to y
  end if
  
–set the end of resYList to aMlen
end repeat

return resYList

on getMlenAndVerifyFirstDaysNum(aYear, aMonth, theNSCalendar, dMax, fdayNum)
  
  
–現在のLocaleのCalendarで指定年月の日数をかぞえる
  
set theDate to theNSCalendar’s dateWithEra:1 |year|:aYear |month|:aMonth |day|:1 hour:0 minute:0 |second|:0 nanosecond:0
  
set theResult to theNSCalendar’s rangeOfUnit:(current application’s NSDayCalendarUnit) inUnit:(current application’s NSMonthCalendarUnit) forDate:theDate
  
–>  {location:1, length:31}
  
set mLen to |length| of theResult
  
  
–指定年月の1日を取得
  
set theDay to theNSCalendar’s components:((current application’s NSWeekdayCalendarUnit) + (current application’s NSMonthCalendarUnit as integer)) fromDate:theDate
  
  
–指定年月の1日の曜日が指定曜日で、うるう月でなく、指定年月の日数が指定日数(dMax)であるか判定
  
if (theDay’s |weekday|() = fdayNum) and (theDay’s isLeapMonth() is false) and (mLen = dMax) then
    return true
  else
    return false
  end if
  
end getMlenAndVerifyFirstDaysNum

★Click Here to Open This Script 

2015/02/02 国際化対応Mlen ASOC版

Shane Stanleyが送ってくれた、国際化対応MlenのASOC版(を、いろいろ検証して修正したもの)です。

そもそも、「Mlen」とは何か? 指定月(例:2012年2月)の日数を求めるMonth Length計算ルーチンです。そして、日本語環境だけではなく他の言語環境でも動くように配慮したものを「国際化対応Mlen」と呼んでいます。

Cocoaの機能を呼び出すようにした本バージョンでは、スピードアップが図られてはいますが、さすがに極小データの処理だけなので数千回ループで回してようやく「速い」とわかるぐらいです。数万件とか数十万件のオーダーになってくると、3倍以上高速かな? という感じです。

AppleScript名:getMlenInternational_ASOC
– Created 2015-02-02 by Shane Stanley
– Modified 2015-02-02 by Takaaki Naganoya
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”

set mList to {}
repeat with m from 1 to 12
  set the end of mList to getMlenInternational(2012, m) of me –2012 is a Leap Year–2012年はうるう年
end repeat
mList
–>  {​​​​​31, ​​​​​29, ​​​​​31, ​​​​​30, ​​​​​31, ​​​​​30, ​​​​​31, ​​​​​31, ​​​​​30, ​​​​​31, ​​​​​30, ​​​​​31​​​}

–現在のカレンダーで指定年月の日数を返す
on getMlenInternational(aYear, aMonth)
  –From Shane’s getMlenInternational(ASOC) v1
  
set theNSCalendar to current application’s NSCalendar’s currentCalendar() – do *not* use initWithCalendarIdentifier:
  
set theDate to theNSCalendar’s dateWithEra:1 |year|:aYear |month|:aMonth |day|:1 hour:0 minute:0 |second|:0 nanosecond:0
  
set theResult to theNSCalendar’s rangeOfUnit:(current application’s NSDayCalendarUnit) inUnit:(current application’s NSMonthCalendarUnit) forDate:theDate
  
–>  {location:1, length:31}
  
return |length| of theResult
end getMlenInternational

★Click Here to Open This Script 

2014/12/08 Remindersのイベントの期日を追加する

リマインダー(Reminders.app)の特定のreminderに対して、「期日」を追加するAppleScriptです。

Twitter上で、reminderに「場所」を追加できないだろうかという問いがあって・・・AppleScriptでは、リマインダー(Reminder.app)のAppleScript用語辞書には「場所」の予約語がないので、そのままでは手も足も出ません。ただ、ASOC経由でCocoaのEventKitにアクセスすれば、できそうな雰囲気がありました。

US AppleのAppleScript Users MLの過去ログをあさってみたら、きわめて近い内容のものがあったので、実際に試してみたら・・・OS X 10.10.1上ではエラーに。

ML上でShane Stanleyに聞いてみたら「10.10上では少々直す必要がある」とのことで、その場で教えてもらえました。ドキュメントを読めば分かる的な話ではあったのですが、Appleのオンラインドキュメントには定数の値が書かれていません(自分はここでスタックしていました)。

・・・どうやらShaneのいう「ドキュメント」とは「ヘッダーファイル」のことだったらしいことに後から気づきました。

# Script Editor上で編集中のAppleScriptのuse文をスキャンして、どのヘッダーファイルをオープンするかをユーザーに尋ねてオープンするAppleScriptを書いておく必要がありそう、、、

とりあえず、本Scriptでは「場所」ではなく「期限」を追加します。さらに調査を行えば、「場所」の追加もできそうですが・・・。

eventkit1.png

iCloud上の「ホーム」というリストにある(最新の)reminderに対して、「期限」を追加します。

eventkit2.png

AppleScript名:Remindersのイベントの期日を追加する
– Created 2014-03-08 by Shane Stanley
– Fixed 2014-12-08 by Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”
use framework “EventKit”

–とりあえず、1つのreminderのIDを取得
tell application “Reminders”
  tell account “iCloud”
    tell list “ホーム”
      set theID to id of (last reminder whose completed is false)
    end tell
  end tell
end tell

set theID to text 20 thru -1 of theID
–> “x-apple-reminder://B63F627B-A177-4CA7-9811-2AEB4875B407″
setDueDate_forReminderID_(((current date) + (2 * days)), theID)

on setDueDate:ASDate forReminderID:theID
  
  
– ASのdateをNSDateに変換
  
set theNSDate to my makeNSDateFrom:ASDate
  
  
– Cocoaのカレンダーを取得
  
set theCalendar to current application’s NSCalendar’s currentCalendar()
  
  
– Components of dateを取得
  
set theComponents to theCalendar’s componentsInTimeZone:(current application’s NSTimeZone’s localTimeZone()) fromDate:theNSDate
  
  
– get event store; 1 means reminders –> 2
  
set eventStore to current application’s EKEventStore’s alloc()’s initWithAccessToEntityTypes:2
  
  
– get the reminder
  
set theReminder to eventStore’s calendarItemWithIdentifier:theID
  
  
– 「期限」の日付を設定する
  
theReminder’s setDueDateComponents:theComponents
  
  
– 保存
  
eventStore’s saveReminder:theReminder commit:true |error|:(missing value)
  
end setDueDate:forReminderID:

on makeNSDateFrom:theASDate
  
  
set {theYear, theMonth, theDay, theSeconds} to theASDate’s {year, month, day, time}
  
  
if theYear < 0 then
    set theYear to -theYear
    
set theEra to 0
  else
    set theEra to 1
  end if
  
  
set theCalendar to current application’s NSCalendar’s currentCalendar()
  
set newDate to theCalendar’s dateWithEra:theEra |year|:theYear |month|:(theMonth as integer) ¬
    |day|:theDay hour:0 minute:0 |second|:theSeconds nanosecond:0
  
  
return newDate
  
end makeNSDateFrom:

★Click Here to Open This Script 

2014/11/06 現在のLocaleのカレンダーの最初の曜日を取得する

現在のログイン中のユーザーアカウントで(システム環境設定の「言語と地域」で)設定しているカレンダーにおける、どの曜日で始まるかの設定を取得するAppleScriptです。

cal1.png

cal2.png

AppleScript名:asoc_現在のLocateのカレンダーの最初の曜日を取得する v2
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aCalendar to current application’s NSCalendar’s currentCalendar()
set aFirstDay to (aCalendar’s firstWeekday)
set c to aFirstDay as integer
–> 1 (Sunday Start Calendar)

–フランス、香港などは月曜日がカレンダーの先頭に来るため結果が異なる
–> 2 (Monday Start Calendar)

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2014/11/04 現在のLocaleのカレンダーのTime Zoneを取得する

現在ログイン中のカレンダー(設定)を取得し、Time Zone名や時差の情報を取得するAppleScriptです。

sys1.png

sys2.png

言語設定によっては、OSレベルで管理しているカレンダーが「日曜日で始まる」か「月曜日で始まる」かといった違いがあります。こうした情報にアクセスするための習作として作成したものです。

GMTとの時差であれば、通常のAppleScriptでも(大昔から)取得できるようになっていますが、どの曜日からカレンダーが始まるかという情報は、Cocoaにアクセスしないとわからないため外せません。

AppleScript名:asoc_現在のLocaleのカレンダーのTime Zoneを取得する
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aCalendar to current application’s NSCalendar’s currentCalendar()
set aTimeZone to (aCalendar’s timeZone)
set tzName to aTimeZone’s |name|() as string
–> “Asia/Tokyo”

set tDiff to (aTimeZone’s secondsFromGMT()) / 3600
–> 9.0

set aDesc to aTimeZone’s |description|() as string
–> “Asia/Tokyo (JST) offset 32400″

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

AppleScript名:普通のASでGMTとの時差を求める
set tDIff to (time to GMT) / 3600
–> 9.0

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2013/11/17 AppleScriptObjCでNSDatePickerに値を設定、取得

AppleScriptObjCで、ウィンドウ上に設置したNSDatePickerに日付の値を設定したり、NSDatePickerから値を取得するサンプルです。

NSDatePicker(以下、DatePicker)は、日付情報を入力するための標準GUI部品。最近は、カレンダー.appで使われているようなカレンダー表示付きのDatePickerなどもあり、これも普通に利用できるとよいでしょう(最悪、自前でカレンダー表示インタフェースを実装してカレンダーから日付を選択してもいいですし)。

DatePickerから値を取得するサンプルは海外のBBSにもあったのですが、DatePickerに日付情報を設定する処理が見つからなかったので、そこを補ってみました。

date1.png
▲起動時にDatePickerに現在の日付を設定

date2.png
▲ボタンをクリックすると、DatePickerから各種日付情報を取り出してダイアログにテスト表示

本サンプルでは、GMT(グリニッジ標準時)との時差を+0000で指定していますが、本来の意味においては正しくないような気がします。日本標準時(JST)はGMT+9.0なので、そのあたりを正しく指定して大丈夫なようにタイムゾーンを考慮してNSDateを指定できるとよいだろうか、と(ぼんやり)考えています。

AppleScriptのdateオブジェクトにはタイムゾーンの要素はないので、AppleScript的な処理の方法とCocoa的な価値観の間で揺れている「どちらから見ても中途半端」な感じのコードになっていますが、AppleScriptObjCのサンプルコードがAppleから出ているわけでもないので、とりあえずは「こうやれば動く」的なコードを出してみて、「ここはこうすべき」的な意見が出れば変えていく、というところでしょうか。

このサンプルが「とりあえず動く」レベルであることを認識する必要があり、同時に複数のタイムゾーン上の日付を扱うと(このレベルの実装だと)混乱するよ、ということを参考までに書いておきます(滅多にないんですけれども)。

本掲載リストは、Xcodeから選択中のAppleScriptファイル(テキストファイル)を取得して、AppleScriptObjC Explorer 2をコントロールしてテキストエディットに書式つきデータでコピペして、テキストエディットからHTML書き出し(AppleScriptで自動処理)しているのですが……Xcodeの外部エディタのAppleScriptObjC Explorer 2を経由するために、ハンドラの書式が「setString_(aVar)」スタイルから、「setString:aVar」スタイルに書き換えられてしまっています。

添付のXcodeプロジェクト中では「setString_(aVar)」スタイルで記述していますので、OS X 10.8上でも編集、実行できるはずです。

→ Xcodeプロジェクトのダウンロード(50KBytes)

AppleScriptObjCファイル名:datePickAppDelegate.applescript

– datePickAppDelegate.applescript
– datePick

– Created by Takaaki Naganoya on 09/11/22.
– Copyright 2009 Takaaki Naganoya. All rights reserved.


script datePickAppDelegate
  property parent : class “NSObject”
  
property datePicker : missing value
  
  
  
  on applicationWillFinishLaunching:aNotification
    
    tell current application
      set aCurDate to current date
      
set aYear to (year of aCurDate) as string
      
set aMonth to (month of aCurDate as number) as string
      
set aDay to (day of aCurDate) as string
      
    end tell
    
    set dStr to aYear & “-” & aMonth & “-” & aDay & ” 00:00:00 +0000″
    
log dStr
    
    set aDate to current application’s NSDate’s dateWithString:dStr
    
log aDate
    
    datePicker’s setDateValue:aDate
    
  end applicationWillFinishLaunching:
  
  on applicationShouldTerminate:sender
    return true
  end applicationShouldTerminate:
  
  
  
  
on clicked:sender
    
    set theDate to my datePicker’s dateValue()
    
set theCal to current application’s class “NSCalendar”’s currentCalendar()
    
set theComponents to theCal’s components:254 fromDate:theDate
    
    –Get Date properties
    
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|()
    
    display dialog ((theYear as text) & return & theMonth as text) & return & theDay as text
    
  end clicked:
  
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に