格式化日本历(和历)

■   介绍

日本的和历是日本特有的纪年法,将每个天皇的统治时期标记为一个纪元。当前的纪元是 平成(Heisei)纪元,始于 1989 年 1 月 8 日。
纪元的名称通常显示在年份前面。例如,公历 2012 年就是日本历的【平成 24 年】。纪元的第一年也称为 元年(Gannen),所以公历 1989 年就是日本历的【平成元年】。

★   纪元列表    
编号
纪元名称
纪元缩写
公历日期
1
平成(Heisei)
平(H, h)
1989 年 01 月 08 日至今 
2
昭和(Showa)
昭(S, s)
1926 年 12 月 25 日至 1989 年 01 月 07 日
3
大正(Taisho)
大(T, t)
1912 年 07 月 30 日至 1926 年 12 月 24 日
4
明治(Meiji)
明(M, m)
1868 年 09 月 08 日至 1912 年 07 月 29 日
5
N/A
N/A
1868 年 09 月 07 日之前

■   Java 6 以后格式化和历的示例代码:

public static void testJapaneseCalendar() throws ParseException {
    SimpleDateFormat d = new SimpleDateFormat("yyyy/MM/dd");

    Locale locale = new Locale("ja", "JP", "JP");
    // 必须这样实例化 Locale,不可使用 Locale.JAPAN 或 Locale.JAPANESE,否则后续的格式化无效
        
    DateFormat ja = DateFormat.getDateInstance(DateFormat.FULL, locale);
    System.out.println(ja.format(d.parse("2012/11/12"))); // 结果是:平成24年11月12日

    ja = new SimpleDateFormat("GGGG yy年MM月dd日", locale);
    System.out.println(ja.format(d.parse("2012/11/12"))); // 结果是:平成_24年11月12日(下划线代表空格)

    ja = DateFormat.getDateInstance(DateFormat.SHORT, locale);
    System.out.println(ja.format(d.parse("2012/11/12"))); // 结果是:H24.11.12

    ja = new SimpleDateFormat("G yy.MM.dd", locale);
    System.out.println(ja.format(d.parse("2012/11/12"))); // 结果是:H_24.11.12(下划线代表空格)

    ja = new SimpleDateFormat("GGGG yy年MM月dd日", locale);
    System.out.println(ja.format(d.parse("1868/01/01"))); // 结果是:明治_01年01月01日(下划线代表空格)

    ja = new SimpleDateFormat("G yy.MM.dd", locale);
    System.out.println(ja.format(d.parse("1868/01/01"))); // 结果是:M_01.01.01(下划线代表空格)

    ja = new SimpleDateFormat("GGGG yy年MM月dd日", locale);
    System.out.println(ja.format(d.parse("1867/12/31"))); // 结果是:西暦_1867年12月31日(下划线代表空格)

    ja = new SimpleDateFormat("G yy.MM.dd", locale);
    System.out.println(ja.format(d.parse("1867/12/31"))); // 结果是:_1867.12.31(下划线代表空格)
}

注意,这里的 Locale 必须实例化成 Locale("ja", "JP", "JP"),否则格式化不出来和历的效果。原因可以通过分析 Calendar 类的 createCalendar() 方法得知,对 Locale("ja", "JP", "JP") 进行了特殊处理,返回了 JapaneseImperialCalendar 这个特殊类的实例,代码如下:
    
private static Calendar createCalendar(TimeZone zone, Locale aLocale)
{
    // If the specified locale is a Thai locale, returns a BuddhistCalendar
    // instance.
    if ("th".equals(aLocale.getLanguage())
        && ("TH".equals(aLocale.getCountry()))) {
        return new sun.util.BuddhistCalendar(zone, aLocale);
    } else if ("JP".equals(aLocale.getVariant())
           && "JP".equals(aLocale.getCountry())
           && "ja".equals(aLocale.getLanguage())) {
        return new JapaneseImperialCalendar(zone, aLocale);
    }        

    // else create the default calendar
    return new GregorianCalendar(zone, aLocale);    
}

补充,JapaneseImperialCalendar 类是 Java 1.6 以后才有的,所以上面的代码只在 Java 1.6 以后的版本有效。

■ 自定义的一个简单实现(旧版本 Java 可用)
   通过修改 DateFormatSymbols 的纪元文字来实现。这样旧版本的 Java 环境上也可以用,也容易实现扩展。

public static String formatJapaneseCalendar(String pattern, Date date, boolean showFullName) {
    SimpleDateFormat format = new SimpleDateFormat(pattern);
    DateFormatSymbols symbols = format.getDateFormatSymbols();
    String[] eras = symbols.getEras();


    GregorianCalendar gregorianCalendar = new GregorianCalendar();
    gregorianCalendar.setTime(date);


    if (!gregorianCalendar.before(HEISEI)) {
        if (showFullName) { eras[0] = "平成"; } else { eras[0] = "H"; }
        gregorianCalendar.set(Calendar.YEAR, HEISEI.get(Calendar.YEAR) - gregorianCalendar.get(Calendar.YEAR));
    } else if (!gregorianCalendar.before(SYOWA)) {
        if (showFullName) { eras[0] = "昭和"; } else { eras[0] = "S"; }
        gregorianCalendar.set(Calendar.YEAR, SYOWA.get(Calendar.YEAR) - gregorianCalendar.get(Calendar.YEAR));
    } else if (!gregorianCalendar.before(TAISYO)) {
        if (showFullName) { eras[0] = "大正"; } else { eras[0] = "T"; }
        gregorianCalendar.set(Calendar.YEAR, TAISYO.get(Calendar.YEAR) - gregorianCalendar.get(Calendar.YEAR));
    } else if (!gregorianCalendar.before(MEIJI)) {
        if (showFullName) { eras[0] = "明治"; } else { eras[0] = "M"; }
        gregorianCalendar.set(Calendar.YEAR, MEIJI.get(Calendar.YEAR) - gregorianCalendar.get(Calendar.YEAR));
    }


    symbols.setEras(eras);
    format.setDateFormatSymbols(symbols);


    return format.format(gregorianCalendar.getTime());
}


/** 明治 */
private static final GregorianCalendar MEIJI = new GregorianCalendar(1868, 0, 1);
/** 大正 */
private static final GregorianCalendar TAISYO = new GregorianCalendar(1912, 6, 30);
/** 昭和 */
private static final GregorianCalendar SYOWA = new GregorianCalendar(1926, 11, 25);
/** 平成 */
private static final GregorianCalendar HEISEI = new GregorianCalendar(1989, 0, 8);








评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值