AppleScript名:自然言語による相対日付指定v15 |
use AppleScript version "2.5" use scripting additions use framework "Foundation" –v15 ASOCの部品に入れ替え、macOS 10.11以降用にハンドラの型強制オプションをつけた –v14 10.8の上で動作するように書き換えた –The Calendar Scripting Module global d3List –3か月カレンダーの格納変数 global d4List –3か月カレンダーBの格納変数(当月の情報しか日付は入っていないカレンダー) global weekCounter — 今日が3か月カレンダーの何週目にあたるか set aDate to calcDate("今日", "") of me log {"今日:" & aDate as text} set aDate to calcDate("先々週", "水曜日") of me log {"先々週の水曜日:" & aDate as text} set aDate to calcDate("来週", "金曜") of me log {"来週の金曜日:" & aDate as text} on calcDate(param1 as string, param2 as string) –相対日付指定パラメータテーブル –data sample: {{"今日", "きょう"}, 0, "date"} –data format:{{"keyword_1", "keyword_2"…."keyword_n"}, vector, "class_of_this_keyword"} –Vector量をその場で(ユーザー環境に応じて)算出もしくは取得する必要がある場合には「999」を設定しておく set dDat to {{{"来年"}, 1, "year"}, {{"今年"}, 0, "year"}, {{"去年"}, -1, "year"}, {{"再来年"}, 2, "year"}, {{"今週"}, 0, "week"}, {{"先週"}, -1, "week"}, {{"先々週"}, -2, "week"}, {{"来週"}, 1, "week"}, {{"再来週"}, 2, "week"}, {{"今日", "きょう"}, 0, "date"}, {{"明日", "あした"}, 1, "date"}, {{"明後日", "あさって"}, 2, "date"}, {{"明々後日", "しあさって"}, 3, "date"}, {{"昨日", "きのう"}, -1, "date"}, {{"一昨日", "おととい"}, -2, "date"}, {{"一昨々日", "さきおととい"}, -3, "date"}, {{"次", "今度", "こんど", "つぎ"}, 1, "variable"}, {{"前"}, -1, "variable"}} –曜日指定パラメータ set wDat to {"日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日", "日曜", "月曜", "火曜", "水曜", "木曜", "金曜", "土曜", "にちようび", "げつようび", "かようび", "すいようび", "もくようび", "きんようび", "どようび", "にちよう", "げつよう", "かよう", "すいよう", "もくよう", "きんよう", "どよう"} –3か月カレンダーを作成 makeCalendar() of me –今日の日付を保持 set todayDate to current date –指定週の計算用ワーク変数 set targetWeek to 0 –指定月の計算用ワーク変数 set targetMonth to (month of todayDate) as number set targetYear to year of todayDate set targetDate to day of todayDate set aItem to "" repeat with i in dDat if param1 is in item 1 of i then copy i to aItem exit repeat end if end repeat if (item 3 of aItem) is "date" then log "Hit date class parameter" –dateレベルのパラメータの場合 set retDate to todayDate + (item 2 of aItem) * days set time of retDate to 0 return retDate –「時刻を問わない」ことを示す表現として、00時を指定してdate型を返す else if item 3 of aItem is "week" then log "hit week class parameter" –weekレベルのパラメータの場合 set targetWeek to weekCounter + (item 2 of aItem) if param2 is in wDat then –パラメータが「何曜日か?」を得る set tmpD to 1 repeat with j in wDat if param2 is contents of j then exit repeat set tmpD to tmpD + 1 end repeat if tmpD > 7 then set tmpD to tmpD mod 7 end if –今月か? if item tmpD of item targetWeek of d4List is 0 then –今月ではない場合 set tmp2 to item tmpD of item targetWeek of d3List if ((item 2 of aItem) < 0) then –今月ではなく、パラメータがマイナスの週計算を行う場合 –先月に入ったので月を減らす set targetMonth to targetMonth – 1 set tmp4 to (targetYear & "/" & targetMonth & "/" & tmp2) as string set ret2Date to date (tmp4 & " 0:00:00") return ret2Date else –来月として処理 set targetMonth to targetMonth + 1 set tmp4 to (targetYear & "/" & targetMonth & "/" & tmp2) as string set ret2Date to date (tmp4 & " 0:00:00") return ret2Date end if else –今月の場合の処理 set tmp2 to item tmpD of item targetWeek of d3List set tmp3 to day of todayDate set tmp4 to (targetYear & "/" & targetMonth & "/" & tmp2) as string set ret2Date to date (tmp4 & " 0:00:00") return ret2Date end if else –ここはエラーを返すべし("来週","")といったパターンになるので —-あるいは、「○○日」といったダイレクトパラメータの処理を行う –日付ダイレクトパラメータの処理 error "日付を特定するためのパラメータがありません" (* ただし、このように決め打ちでエラーメッセージを返すような実装は暫定仕様。 何が欠けているかをGUIフィードバックするのが最終的な実装 *) end if else if item 3 of aItem is "month" then –monthレベルのパラメータの場合 log "Hit month class parameter" else if item 3 of aItem is "year" then –yearレベルのパラメータの場合 log "Hit year class parameter" end if return "no hit" end calcDate –相対日付計算用の3か月カレンダーを作成する on makeCalendar() set aToday to current date –とりあえず、当月の情報を収集する set y1 to getYear(aToday) of me set m1 to getMonth(aToday) of me set d1 to getDate(aToday) of me set dy1 to getDay(aToday) of me set mlen1 to getMlen(y1, m1) of me set mXDay to getDay(aToday) of me –今日の曜日 –前月の情報を組み立てる if m1 is not equal to 1 then –2〜12月の場合 set y0 to y1 set m0 to m1 – 1 else –1月の場合 set y0 to y1 – 1 set m0 to 12 end if –前月の月の長さ set mLen0 to getMlen(y0, m0) of me –前月のみ開始日の曜日を求めておく必要がある(3か月カレンダーを作るため) set m0Date to (y0 & "/" & m0 & "/1 0:00:00") as text set m0Date to date m0Date set m0Day to getDay(m0Date) of me –1日の曜日 –翌月の情報を組み立てる if m1 is not equal to 12 then –1〜11月の場合 set y2 to y1 set m2 to m1 + 1 else –12月の場合 set y2 to y1 + 1 set m2 to 1 end if –翌月の月の長さ set mLen2 to getMlen(y2, m2) of me –3か月カレンダーの格納変数 set d3List to {} –3か月カレンダーBの格納変数(当月の情報しか日付は入っていないカレンダー) set d4List to {} set gapList to {0, 0, 0, 0, 0, 0, 0} set w1temp to items 1 thru (m0Day) of gapList set w2temp to items 1 thru (m0Day) of gapList set dayCounter to 1 –最初の1週目の要素を組み立てる repeat with i from m0Day to 7 set the end of w1temp to dayCounter set the end of w2temp to 0 set dayCounter to dayCounter + 1 end repeat set the end of d3List to w1temp set the end of d4List to w2temp set w1temp to {} set w2temp to {} –前月の通常処理 repeat repeat with i from 1 to 7 set the end of w1temp to dayCounter set the end of w2temp to 0 set dayCounter to dayCounter + 1 if dayCounter > mLen0 then exit repeat end repeat if dayCounter > mLen0 then exit repeat set the end of d3List to w1temp set the end of d4List to w2temp set w1temp to {} set w2temp to {} end repeat –ここから当月処理 –1週目 if i = 7 then set ii to 1 set the end of d3List to w1temp set the end of d4List to w2temp set w1temp to {} set w2temp to {} else set ii to i + 1 end if set dayCounter to 1 –日付カウンタの初期化 repeat with j from ii to 7 set the end of w1temp to dayCounter set the end of w2temp to dayCounter set dayCounter to dayCounter + 1 end repeat set the end of d3List to w1temp set the end of d4List to w2temp set w1temp to {} set w2temp to {} –当月の2週目以降 repeat repeat with j from 1 to 7 set the end of w1temp to dayCounter set the end of w2temp to dayCounter set dayCounter to dayCounter + 1 if dayCounter > mlen1 then exit repeat end repeat if dayCounter > mlen1 then exit repeat set the end of d3List to w1temp set the end of d4List to w2temp set w1temp to {} set w2temp to {} end repeat –ここから翌月処理 –1週目 if j = 7 then set iii to 1 set the end of d3List to w1temp set the end of d4List to w2temp set w1temp to {} set w2temp to {} else set iii to j + 1 end if set dayCounter to 1 –日付カウンタの初期化 repeat with j from iii to 7 set the end of w1temp to dayCounter set the end of w2temp to 0 set dayCounter to dayCounter + 1 end repeat set the end of d3List to w1temp set the end of d4List to w2temp set w1temp to {} set w2temp to {} –翌月の2週目以降 repeat repeat with k from 1 to 7 set the end of w1temp to dayCounter set the end of w2temp to 0 set dayCounter to dayCounter + 1 if dayCounter > mlen1 then exit repeat end repeat if dayCounter > mlen1 then exit repeat set the end of d3List to w1temp set the end of d4List to w2temp set w1temp to {} set w2temp to {} end repeat if length of w1temp is not equal to 0 then set the end of d3List to w1temp set the end of d4List to w2temp end if –ここまで3か月カレンダーの生成 –3か月カレンダーにおいて今日が何週目かを算出 set weekCounter to 1 repeat with aWeek in d4List –裏リストで操作を行う –ただし、該当曜日しかチェックしないので全チェックに比べて速度7倍 set aDay to (item mXDay of aWeek) as number if aDay = (d1 as number) then exit repeat end if set weekCounter to weekCounter + 1 end repeat end makeCalendar –現在日時から曜日を取得を返す on getDay(aDate as date) return (weekday of aDate) as number end getDay –指定日の月のみ返す on getMonth(aDat as date) return (month of aDat) as number end getMonth –指定日の日付のみ返す on getDate(aDat as date) return (day of aDat) as number end getDate –指定日の年のみ返す on getYear(aDat as date) return (year of aDat) as number end getYear –現在のカレンダーで指定年月の日数を返す(国際化対応版) on getMlen(aYear as integer, aMonth as integer) set theNSCalendar to current application’s NSCalendar’s currentCalendar() 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 return |length| of theResult end getMlen |
More from my site
(Visited 35 times, 1 visits today)