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

#きっかけ

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

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

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

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

#仕様

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

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

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

    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
を指定してあげるだけです。

#コード その２
ほとんど同じ内容のメソッドをいくつも用意するのはスマートじゃないので
前月か当月か翌月か～を引数で指定できるようにしてまとめたのも置いておきます。
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月 ` ` ` 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/cad3449b-7b0e-88fb-58f6-452628832674.png)
年をまたいでもいい感じに取れます！

 ` ` ` 99年99月 ` ` ` 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/cd68044a-56f2-6fc7-c5df-c3e2ddaab78c.png)
年は4桁数値なので1000～9999かゼロパディングした値しかマッチしません。月は1～12のみOKです。

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



#参考
https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_methods_system_date.htm

https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_pattern_and_matcher_pattern_methods.htm

https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_pattern_and_matcher_matcher_methods.htm#apex_classes_pattern_and_matcher_matcher_methods