Pleasanterで、先週とか来月のようなフィルタリングをしたい。

# 前置き
Pleasnaterのサーバスクリプト、[view.Filters](https://pleasanter.org/manual/server-script-view-filters)で実現します。

view.Filter自体はマニュアルに書いてあること以上のポイントはありません。日付のFrom Toをどのように設定するか、主にJavascriptの話がメインになります。

基本的に、操作日「今日」を基準にフィルタを設定していきます。

# view.Filtersの設定とユーティリティ関数

基本となるview.Filtersの設定と、日付項目を所定の形式にするための関数です。Pleasanterのサーバスクリプトに、条件「ビュー処理時」を設定します。

また、事前に各フィルタを有効にするための[ビュー](https://pleasanter.org/manual/table-management-view)を用意し、紐づくview.Idにしかるべきフィルタ日付を設定します。フィルタする項目は、完了日(CompletionTime)です。

今回の例では、以下のようにビューを設定します。

|view.Id|設定するフィルタ|
|:--|:--|
|1|今週|
|2|先週|
|3|来週|
|4|先月|
|5|今月|
|6|来月|

view.Idを置き換えてもらえれば、使いまわせるはずです。

```javascript

//日付の形式変換関数(yyyy/MM/dd形式)
const convDateStr = (date) => {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}/${month}/${day}`;
}

//メインとなる処理
try {
    const today = new Date();

    let filterPeriod;

    //ビューを設定しておきます。
    switch (view.Id){
        case 1:
            //今週
            filterPeriod = getPeriodOfThisWeek(today);
            break;
        case 2:
            //先週
            filterPeriod = getPeriodOfLastWeek(today);
            break;
        case 3:
            //来週
            filterPeriod = getPeriodOfNextWeek(today);
            break;
        case 4:
            //今月
            filterPeriod = getPeriodOfThisMonth(today);
            break;
        case 5:
            //先月
            filterPeriod = getPeriodOfLastMonth(today);
            break;
        case 6:
            //来月
            filterPeriod = getPeriodOfNextMonth(today);
            break;
        default:
            filterPeriod = ""
            break;
            
    }

    if(!filterPeriod){
        view.Filters.CompletionTime = ""
    }else{
        context.Log("フィルタ : " + filterPeriod);
        view.Filters.CompletionTime = `["${filterPeriod}"]`;
    }

} catch (e) {
    context.Log(e.stack);
}
```


# 先週・今週・来週

「今日」の日付を各関数の引数で受け取り、日付を計算します。なお、月曜始まり～日曜終わりで取得するようになっています。

```javascript
//先週
const getPeriodOfLastWeek = (date) => {
    
    //先週月曜を取得
    const lastMonday = new Date(
        date.getFullYear(), 
        date.getMonth(), 
        date.getDate() - date.getDay() - 6);

    //先週日曜を取得
    const lastSunday = new Date(
        date.getFullYear(), 
        date.getMonth(), 
        date.getDate() - date.getDay());
    
    return `${convDateStr(lastMonday)} 00:00:00,${convDateStr(lastSunday)} 23:59:59`;
}

//今週
const getPeriodOfThisWeek = (date) => {

    //今週月曜を取得
    const thisMonday = new Date(
        date.getFullYear(), 
        date.getMonth(), 
        date.getDate() - date.getDay() + 1);

    //今週日曜を取得
    const thisSunday = new Date(
        date.getFullYear(), 
        date.getMonth(), 
        date.getDate() - date.getDay() + 7);

    return `${convDateStr(thisMonday)} 00:00:00,${convDateStr(thisSunday)} 23:59:59`;
}

//来週
const getPeriodOfNextWeek = (date) => {

    //来週月曜を取得
    const nextMonday = new Date(
        date.getFullYear(), 
        date.getMonth(), 
        date.getDate() - date.getDay() + 8);

    //来週日曜を取得
    const nextSunday = new Date(
        date.getFullYear(), 
        date.getMonth(), 
        date.getDate() - date.getDay() + 14);

    return `${convDateStr(nextMonday)} 00:00:00,${convDateStr(nextSunday)} 23:59:59`;
}
```

ポイントは、getDay()。これで、任意の日付から見た特定の曜日を取得しています。詳細は[リファレンス](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/getDay)参照。

日付に対して、日曜から土曜までを示す値0～6が返却されます。これを日付に対し加減算することで、 **「任意の日付に対する特定の曜日の日付」** を取得することができます。（日本語難しい）

わかりにくいので、確認用のスクリプトを用意しました。

```javascript
const convDateStr = (date) => {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}/${month}/${day}`;
}

const getDayHash = [
    {
        value:0,
        dayOfWeek:'日曜'
    },
    {
        value:1,
        dayOfWeek:'月曜'
    },
    {
        value:2,
        dayOfWeek:'火曜'
    },
    {
        value:3,
        dayOfWeek:'水曜'
    },
    {
        value:4,
        dayOfWeek:'木曜'
    },
    {
        value:5,
        dayOfWeek:'金曜'
    },
    {
        value:6,
        dayOfWeek:'土曜'
    }
]

const getSunday = (strDate) => {
    let inDate = new Date(strDate)
    const inDateOfWeek = getDayHash.filter(x => x.value === inDate.getDay())[0].dayOfWeek
    
    let getDay = getDayHash.filter(x => x.value === inDate.getDay());
    
    //入力日から見た日曜は
    const outDate = new Date(inDate.getFullYear(), inDate.getMonth(), inDate.getDate() - inDate.getDay());
    const outDateOfWeek = getDayHash.filter(x => x.value === outDate.getDay())[0].dayOfWeek;
    console.log(`input:${convDateStr(inDate)}(${inDateOfWeek}) 
        - getDay:${inDate.getDay()} 
        = sunday:${convDateStr(outDate)}(${outDateOfWeek})`)
}

let strDateList = [
    '2024/1/22',
    '2024/1/23',
    '2024/1/24',
    '2024/1/25',
    '2024/1/26',
    '2024/1/27',
    '2024/1/28',
    '2024/1/29',
    '2024/1/30'
];

strDateList.map(strDate => {getSunday(strDate)})

```

strDateListに設定した各日付に対する、日曜の日付を算出します。開発者ツールのコンソール貼り付けで動くはず。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/dfff05f2-fd6d-78c1-9f38-210e3ff15097.png)

あとはそこから加減算して、求めたい期間を計算・編集するだけ。

# 今月・先月・来月

「今日」の日付を受け取るのは同じ。週単位よりも簡単。

```javascript
//今月
const getPeriodOfThisMonth = (date) => {
    
    // 今月１日を取得
    const firstDayOfThisMonth = new Date(
        date.getFullYear(), 
        date.getMonth(), 
        1);

    // 来月１日を取得
    const firstDayOfNextMonth = new Date(
        date.getFullYear(), 
        date.getMonth() + 1, 
        1);

    // 来月１日からマイナス１日して先月末日を取得
    const lastDayOfThisMonth = new Date(firstDayOfNextMonth - 1);
   
    return `${convDateStr(firstDayOfThisMonth)} 00:00:00,${convDateStr(lastDayOfThisMonth)} 23:59:59`;
}

//先月
const getPeriodOfLastMonth = (date) => {
    
    // 先月の最初の日を取得
    const firstDayOfLastMonth = new Date(
        date.getFullYear(), 
        date.getMonth() - 1, 
        1);

    // 今月１日を取得
    const firstDayOfThisMonth = new Date(
        date.getFullYear(), 
        date.getMonth(), 
        1);

    // 今月１日からマイナス１日して先月末日を取得
    const lastDayOfLastMonth = new Date(firstDayOfThisMonth - 1);
   
    return `${convDateStr(firstDayOfLastMonth)} 00:00:00,${convDateStr(lastDayOfLastMonth)} 23:59:59`;
}

//来月
const getPeriodOfNextMonth = (date) => {
    
    // 来月の最初の日を取得
    const firstDayOfNextMonth = new Date(
        date.getFullYear(), 
        date.getMonth() + 1, 
        1);

    // 再来月の１日を取得
    const firstDayOfMonthAfterNext = new Date(
        date.getFullYear(), 
        date.getMonth() + 2, 
        1);

    // 再来月の１日からマイナス１日して来月末日を取得
    const lastDayOfNextMonth = new Date(firstDayOfMonthAfterNext - 1);
   
    return `${convDateStr(firstDayOfNextMonth)} 00:00:00,${convDateStr(lastDayOfNextMonth)} 23:59:59`;
}
```

ポイントは月末日の取得方法。考え方は、
1. 求めたい月の翌月１日を設定
1. そこからマイナス１日する

Dateオブジェクトが末日を、良い感じに取得してきてくれます。

# 補足
- サーバスクリプトで日付を計算する場合、サーバ・DBのタイムゾーンに依存します。環境によってはその点の考慮が必要になる可能性があるので、ご注意ください。
- getFullYear()、getMonth()、getDate()については、「Javascript 日付計算」でいろいろリファレンスがあるのでそっちを参照してください。