Skip to content

Instantly share code, notes, and snippets.

@tenten0213
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tenten0213/78d67488977492628236 to your computer and use it in GitHub Desktop.
Save tenten0213/78d67488977492628236 to your computer and use it in GitHub Desktop.
西暦和暦変換
package util;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class DateUtil {
private static final Locale LOCALE_JA = new Locale("ja", "JP", "JP");
public static String dateToJapaneseCalendar(Date date, String format) {
DateFormat japaseseFormat = new SimpleDateFormat(format, LOCALE_JA);
return japaseseFormat.format(date);
}
public static Date japaneseCalendarToDate(String jpDateStr, String format) throws ParseException {
DateFormat japaseseFormat = new SimpleDateFormat(format, LOCALE_JA);
return japaseseFormat.parse(jpDateStr);
}
// こんな実装になる設計書出された
public static String warekiToSeireki(String gengoKbn, String wareki) {
int warekiYear = Integer.parseInt(wareki.substring(0,2));
String warekiMD = wareki.substring(2,6);
switch (gengoKbn){
case "M":
warekiYear = warekiYear + 1867;
break;
case "T":
warekiYear = warekiYear + 1911;
break;
case "S":
warekiYear = warekiYear + 1925;
break;
case "H":
warekiYear = warekiYear + 1988;
break;
default:
throw new IllegalArgumentException("argument is wrong");
}
return String.valueOf(warekiYear) + warekiMD;
}
}
package util;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
public class DateUtilTest {
// 平成y年M月d日
static final String japaneseEraFormat = "GGGGy年M月d日";
// Hy年M月d日
static final String japaneseEraAlphabetFormat = "GGGy年M月d日";
@Test
public void 西暦和暦変換漢字フォーマットの場合() throws ParseException {
Date date = DateFormat.getDateInstance().parse("1986/02/13");
assertThat(DateUtil.dateToJapaneseCalendar(date, japaneseEraFormat), is("昭和61年2月13日"));
}
@Test
public void 西暦和暦変換アルファベットフォーマットの場合() throws ParseException {
Date date = DateFormat.getDateInstance().parse("1986/02/13");
assertThat(DateUtil.dateToJapaneseCalendar(date, japaneseEraAlphabetFormat), is("S61年2月13日"));
}
@Test
public void 西暦和暦変換実在しない日の場合() throws ParseException {
Date date = DateFormat.getDateInstance().parse("1986/13/40");
// 加算された日付が返る
assertThat(DateUtil.dateToJapaneseCalendar(date, japaneseEraFormat), is("昭和62年2月9日"));
}
@Test
public void 和暦西暦変換漢字フォーマットの場合() throws ParseException {
Date date = DateFormat.getDateInstance().parse("1986/02/13");
assertThat(DateUtil.japaneseCalendarToDate("昭和61年2月13日", japaneseEraFormat), is(date));
}
@Test
public void 和暦西暦変換アルファベットフォーマットの場合() throws ParseException {
Date date = DateFormat.getDateInstance().parse("1986/02/13");
assertThat(DateUtil.japaneseCalendarToDate("S61年2月13日", japaneseEraAlphabetFormat), is(date));
}
@Test
public void 境界値テスト平成昭和() throws ParseException {
Date HEISEI_START = DateFormat.getDateInstance().parse("1989/01/08");
Date SHOWA_END = DateFormat.getDateInstance().parse("1989/01/07");
assertThat(DateUtil.dateToJapaneseCalendar(HEISEI_START, japaneseEraFormat), is("平成1年1月8日"));
assertThat(DateUtil.dateToJapaneseCalendar(SHOWA_END, japaneseEraFormat), is("昭和64年1月7日"));
}
@Test
public void 境界値テスト昭和大正() throws ParseException {
Date SHOWA_START = DateFormat.getDateInstance().parse("1926/12/25");
Date TAISHO_END = DateFormat.getDateInstance().parse("1926/12/24");
assertThat(DateUtil.dateToJapaneseCalendar(SHOWA_START, japaneseEraFormat), is("昭和1年12月25日"));
assertThat(DateUtil.dateToJapaneseCalendar(TAISHO_END, japaneseEraFormat), is("大正15年12月24日"));
}
@Test
public void 境界値テスト大正明治() throws ParseException {
Date TAISHO_START = DateFormat.getDateInstance().parse("1912/07/30");
Date MEIJI_END = DateFormat.getDateInstance().parse("1912/07/29");
assertThat(DateUtil.dateToJapaneseCalendar(TAISHO_START, japaneseEraFormat), is("大正1年7月30日"));
assertThat(DateUtil.dateToJapaneseCalendar(MEIJI_END, japaneseEraFormat), is("明治45年7月29日"));
}
@Test
public void 境界値テスト明治慶応() throws ParseException {
// 明治の始まりは、法的には1868年1月1日
Date MEIJI_START = DateFormat.getDateInstance().parse("1868/01/01");
Date KEIO_END = DateFormat.getDateInstance().parse("1867/12/31");
assertThat(DateUtil.dateToJapaneseCalendar(MEIJI_START, japaneseEraFormat), is("明治1年1月1日"));
// 明治以前の元号は変換出来ない
assertThat(DateUtil.dateToJapaneseCalendar(KEIO_END, japaneseEraFormat), is("西暦1867年12月31日"));
}
@Test
public void 境界値テスト明治慶応_和暦西暦() throws ParseException {
// 明治の始まりは、法的には1868年1月1日
Date MEIJI_START = DateFormat.getDateInstance().parse("1868/01/01");
Date KEIO_END = DateFormat.getDateInstance().parse("1867/12/31");
assertThat(DateUtil.japaneseCalendarToDate("明治1年1月1日", japaneseEraFormat), is(MEIJI_START));
// 明治以前の元号は変換出来ない…けど、西暦だと動いたり
assertThat(DateUtil.japaneseCalendarToDate("西暦1867年12月31日", japaneseEraFormat), is(KEIO_END));
}
@Test(expected = ParseException.class)
public void 境界値テスト明治慶応_和暦西暦パースエラー() throws ParseException {
Date KEIO_END = DateFormat.getDateInstance().parse("1867/12/31");
// 明治以前の元号は変換出来ない
DateUtil.japaneseCalendarToDate("慶応3年12月31日", japaneseEraFormat);
}
@Test
public void 和暦西暦変換日立() {
assertThat(DateUtil.warekiToSeireki("H", "261020"), is("20141020"));
}
@Test(expected = IllegalArgumentException.class)
public void 和暦西暦変換日立_区分例外() {
DateUtil.warekiToSeireki("K", "261020");
}
@Test(expected = NumberFormatException.class)
public void 和暦西暦変換日立_引数が数字じゃないと例外() {
DateUtil.warekiToSeireki("H", "a61020");
}
@Test
public void 和暦西暦変換日立_桁数があっていない場合() {
// メソッドの作り次第だけど…
assertThat(DateUtil.warekiToSeireki("H", "26123030"), is("20141230"));
}
@Test
public void 和暦西暦変換日立_実在しない日付() {
assertThat(DateUtil.warekiToSeireki("H", "269999"), is("20149999"));
}
@Test
public void 和暦西暦変換アレ_真面目に使おうとすると() throws Exception {
String gengo = "平成"; //どっかから取得
String warekiYMD = "26/10/20"; //どっかから取得
String wareki = warekiYMD.replaceAll("/", "");
String gengoKbn = getGengoKbn(gengo);
String seireki = "";
// 実在日チェックどうする?
if (StringUtils.isNumeric(wareki) && wareki.length() == 6) {
seireki = DateUtil.warekiToSeireki(gengoKbn, "261020");
} else {
throw new Exception("エラー");
}
assertThat(seireki, is("20141020"));
}
private String getGengoKbn(String gengo) {
switch (gengo){
case "明治":
return "M";
case "大正":
return "T";
case "昭和":
return "S";
case "平成":
return "H";
default:
return "";
}
}
@Test
public void 和暦西暦変換アレ_境界値平成昭和() {
assertThat(DateUtil.warekiToSeireki("H", "010108"), is("19890108"));
assertThat(DateUtil.warekiToSeireki("S", "640107"), is("19890107"));
}
@Test
public void 和暦西暦変換アレ_境界値昭和大正() {
assertThat(DateUtil.warekiToSeireki("S", "011225"), is("19261225"));
assertThat(DateUtil.warekiToSeireki("T", "151224"), is("19261224"));
}
@Test
public void 和暦西暦変換アレ_境界値大正明治() {
assertThat(DateUtil.warekiToSeireki("T", "010730"), is("19120730"));
assertThat(DateUtil.warekiToSeireki("M", "450729"), is("19120729"));
}
}
@tenten0213
Copy link
Author

和暦西暦変換処理のロジックとして以下のマトリクスが提示されて???ってなったので書いた。

元号 求める西暦年
明治 和暦年 + 1867
大正 和暦年 + 1911
昭和 和暦年 + 1925
平成 和暦年 + 1988

例外は考慮していない。
目的は元号間の境界値の確認。(元号が渡されるならロジックは合ってるか…)

ちなみに、Java8だと以下が増えているので、違う書き方が出来る。

@tenten0213
Copy link
Author

SimpleDateFormatはスレッドセーフじゃない点に注意。
使い方的には毎回インスタンス生成してるから大丈夫なはず。

複数スレッドで使われるような場合はJava8のDateTimeFormatterがスレッドセーフなので楽に実装出来そう。
Java7以前だと、ThreadLocalとかsynchronizedで囲むとかそんな感じ。

@tenten0213
Copy link
Author

以下のフォーマット指定、

  @Test
    public void 和暦西暦変換アルファベットフォーマットの場合() throws ParseException {
        Date date = DateFormat.getDateInstance().parse("1986/02/13");
        assertThat(DateUtil.japaneseCalendarToDate("S61年2月13日", japaneseEraAlphabetFormat), is(date));
    } 

japaneseEraFormatにしてもテスト通る…

  @Test
    public void 和暦西暦変換アルファベットフォーマットの場合() throws ParseException {
        Date date = DateFormat.getDateInstance().parse("1986/02/13");
        assertThat(DateUtil.japaneseCalendarToDate("S61年2月13日", japaneseEraFormat), is(date));
    } 

致命的じゃないけど気持ち悪い…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment