【Salesforce】【Apex】正規表現で年月テキストから月末日を取得する


きっかけ

yyyy年m月のフォーマットで値が登録されている選択リスト項目があり
その当月末日の値をそれぞれ日付項目にセットしてほしい。

という感じのご要望があったので実装しました。ApexのPatternクラスを使用します。

今回は 正規表現で年月テキストから年と月を取得し、日付型で月末日を返すメソッド の紹介です。
当月末日のほかに前月末日、翌月末日も用意しました。

Patternクラス(正規表現)を使用した処理については、もう一つ記事を書いていますのでこちら↓もご参考ください。
【Salesforce】【Apex】正規表現でテキスト内から指定文字列を複数取得する

仕様

選択リスト項目の値のフォーマット「yyyy年m月」
 例:1999年12月、2020年1月 など

これらの値を引数にいれて、正規表現で年と月を取得し、日付型で月末日を返します。
※引数が不正な値で日付が取れなかった場合はNULLを返します。

コード その1

メソッドを置いておきます。
使用したいクラスにコピペして呼び出せば使用できると思います。
前月末日

public static Date getLastDayOfPreviousMonth(String text){

    // 年月の正規表現
    String regex = '([0-9]{4})年([1-9]|1[0-2])月';

    // 正規表現をPatternにコンパイルし、textに一致するMatcherを作成する
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(text);

    if (m.find()){
        Integer year = Integer.valueOf(m.group(1));
        Integer month = Integer.valueOf(m.group(2));   
        return Date.newInstance(year, month, 0);
    }

    return NULL;

}

当月末日

public static Date getLastDayOfTheMonth(String text){

    // 年月の正規表現
    String regex = '([0-9]{4})年([1-9]|1[0-2])月';

    // 正規表現をPatternにコンパイルし、textに一致するMatcherを作成する
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(text);

    if (m.find()){
        Integer year = Integer.valueOf(m.group(1));
        Integer month = Integer.valueOf(m.group(2));   
        return Date.newInstance(year, month + 1, 0);
    }

    return NULL;

}

翌月末日

public static Date getLastDayOfNextMonth(String text){

    // 年月の正規表現
    String regex = '([0-9]{4})年([1-9]|1[0-2])月';

    // 正規表現をPatternにコンパイルし、textに一致するMatcherを作成する
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(text);

    if (m.find()){
        Integer year = Integer.valueOf(m.group(1));
        Integer month = Integer.valueOf(m.group(2));   
        return Date.newInstance(year, month + 2, 0);
    }

    return NULL;

}

・引数の文字列から正規表現にマッチする値をMatcher.find()で検索
・取得した年月文字列をInteger.valueOf()で数値に変換
・Date.newInstance()で月末日の値を取得
の3つがポイントです。

Date.newInstance(year, month, day) ですが、dayを0で指定してあげるとmonthの前月末日になります。
当月末日が取りたい場合は month + 1
翌月末日が取りたい場合は month + 2
を指定してあげるだけです。

コード その2

ほとんど同じ内容のメソッドをいくつも用意するのはスマートじゃないので
前月か当月か翌月か~を引数で指定できるようにしてまとめたのも置いておきます。
addMonthNum 次第で前々月末日も翌々月末日も取得できますね!

/**
 * 年月テキストから月末日付を取得する
 * @param text 年月テキスト フォーマット:yyyy年m月 
 * @param addMonthNum 0:前月末日, 1:当月末日, 2:翌月末日
 * @return 月末日付
 */
public static Date getLastDayOfMonth(String text, Integer addMonthNum){

    // 年月の正規表現
    String regex = '([0-9]{4})年([1-9]|1[0-2])月';

    // 正規表現をPatternにコンパイルし、textに一致するMatcherを作成する
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(text);

    if (m.find()){
        Integer year = Integer.valueOf(m.group(1));
        Integer month = Integer.valueOf(m.group(2));   
        return Date.newInstance(year, month + addMonthNum, 0);
    }

    return NULL;

}

結果

いくつかの値で匿名実行したログを載せておきます。

1999年12月

年をまたいでもいい感じに取れます!

99年99月

年は4桁数値なので1000~9999かゼロパディングした値しかマッチしません。月は1~12のみOKです。

取りたい日付によって正規表現うまくを直したり、取得後の日付の値を判定したりは適宜お願いします。

参考