没有年份的java本地时间格式

时间:2012-03-15 13:32:54

标签: java localization date-format

我喜欢将本地时间格式格式化为没有年份的字符串。目前我能够显示包含年份的本地格式:

java.text.DateFormat df = java.text.DateFormat.getDateInstance(java.text.DateFormat.SHORT);
String dateString = df.format(date);

因此我收到时间字符串输出,如

12.03.2012
03/12/2012

适用于不同的国家/地区。现在我想得到像

这样的简短形式
12.03.
03/12

我该怎么做?

感谢您的帮助!

8 个答案:

答案 0 :(得分:13)

您可以使用SimpleDateFormat

Date date = new Date();
java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("MM/dd");
String dateString = df.format(date);

输出:

03/15

修改

在进一步研究语言环境格式并扩展Peters答案之后,以下是toPattern()toLocalizedPattern()之间示例差异的一些代码:

import java.text.*
import java.util.*

ArrayList<Locale> locales = new ArrayList<Locale>();
locales.add(Locale.US);
locales.add(Locale.UK);
locales.add(Locale.GERMANY);
locales.add(Locale.CHINA);

Date date = new Date();

for(Locale l : locales)
{
    SimpleDateFormat sdf = (SimpleDateFormat) SimpleDateFormat.getDateInstance(DateFormat.SHORT, l);
    String pattern = sdf.toPattern();
    String localizedPattern = sdf.toLocalizedPattern()
    println "country: " + l.getDisplayName();
    println "pattern: " + pattern;
    println "localizedPattern: " + localizedPattern;

    try {
        SimpleDateFormat temp = new SimpleDateFormat(localizedPattern, l);
        println "localized pattern re-parsed successfully"
    } catch (IllegalArgumentException e) {
        println "localized pattern re-parsed unsuccessfully: " + e.getMessage();
    }
    SimpleDateFormat df = new SimpleDateFormat(pattern, l);
    String dateString = df.format(date);
    println "resulting date: " + dateString
    String yearlessPattern = pattern.replaceAll("\\W?[Yy]+\\W?", "");
    println "yearlessPattern = " + yearlessPattern;
    SimpleDateFormat yearlessSDF = new SimpleDateFormat(yearlessPattern, l);
    println "resulting date without year: " + yearlessSDF.format(date) + "\n";
}

产生以下输出:

country: English (United States)
pattern: M/d/yy
localizedPattern: M/d/yy
localized pattern re-parsed successfully
resulting date: 3/15/12
yearlessPattern = M/d
resulting date without year: 3/15

country: English (United Kingdom)
pattern: dd/MM/yy
localizedPattern: dd/MM/yy
localized pattern re-parsed successfully
resulting date: 15/03/12
yearlessPattern = dd/MM
resulting date without year: 15/03

country: German (Germany)
pattern: dd.MM.yy
localizedPattern: tt.MM.uu
localized pattern re-parsed unsuccessfully: Illegal pattern character 't'
resulting date: 15.03.12
yearlessPattern = dd.MM
resulting date without year: 15.03

country: Chinese (China)
pattern: yy-M-d
localizedPattern: aa-n-j
localized pattern re-parsed unsuccessfully: Illegal pattern character 'n'
resulting date: 12-3-15
yearlessPattern = M-d
resulting date without year: 3-15

总而言之,要显示没有一年的本地化日期:

String yearlessPattern = DateFormat.getDateInstance(DateFormat.SHORT).toPattern().replaceAll("\\W?[Yy]+\\W?", "");

答案 1 :(得分:8)

我需要将日期转换为字符串删除年份。字符串应保持区域设置。日期格式的类型为DateFormat.LONG,而非DateFormat.SHORT。例如,完整字符串为September 18, 2012,而不是09/18/12

我的解决方案(基于Alex帖子):

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.regex.Pattern;

public class Test {


private static void testLocaleDates() {
    String fmtString = "%-20s %-25s %-25s %-20s %-20s";
    System.out.println(String.format(fmtString, "Locale", "Complete date", "Pattern", "Yearless date", "Yearless pattern"));
    Pattern regExpPattern = Pattern.compile("Sweden|Spain|Russia|Ukraine|States|France|German|Japan|China", Pattern.CASE_INSENSITIVE);

    for (Locale locale : Locale.getAvailableLocales()) {
        boolean isPrint = regExpPattern.matcher(locale.getDisplayCountry()).find(); 
        if (!isPrint)
            continue;
        Date date = new Date();
        String dateTxt = DateFormat.getDateInstance(DateFormat.LONG, locale).format(date);
        SimpleDateFormat sdf = (SimpleDateFormat) SimpleDateFormat.getDateInstance(DateFormat.LONG, locale);
        String pattern = sdf.toPattern();
        // Checking 'de' we omit problems with Spain locale
        String regExpPatternTxt = pattern.contains("de") ? "[^Mm]*[Yy]+[^Mm]*" : "[^DdMm]*[Yy]+[^DdMm]*";
        String yearlessPattern = pattern.replaceAll(regExpPatternTxt, "");
        SimpleDateFormat yearlessSDF = new SimpleDateFormat(yearlessPattern, locale);

        System.out.println(String.format(fmtString, locale.getDisplayCountry(), dateTxt, pattern, yearlessSDF.format(date), yearlessPattern));
    }
}

public static void main(String[] args) {
    testLocaleDates();
}
}

节目输出:

区域设置 完成日期 模式 无年级日期 无年级模式
日本 2012年9月18日 YYYY / MM / DD 09/18 MM / DD
日本 H24.09.18 Gy.MM.dd 09.18 MM.DD
美国 2012年9月18日 MMMM d,yyyy 9月18日 MMMM d
西班牙 18 de septiembre de 2012 d'de'MMMM'de'yyyy 18 de septiembre d 'de'MMMM
美国 18 de septiembre de 2012 d'de'MMMM'de'yyyy 18 de septiembre d'de'MMMM
乌克兰 2012年12月 d MMMM yyyy 18вересня d MMMM
西班牙 18 / setembre / 2012 d'/'MMMM'/'yyyy 18 / setembre d '/'MMMM
俄罗斯 18Сентябрь2012г。 d MMMMyyyy'г。' 18Сентябрь d MMMM
中国 2012年9月18日 YYYY '年' M '月' d '日' 9月18日 M '月' d '日'
法国 18 septembre 2012 d MMMM yyyy 18 septembre d MMMM
德国 18。 2012年9月 d。 MMMM yyyy 18。九月 d。 MMMM
瑞典 2012年9月18日 'den'd MMMM yyyy den 18 september 'den'd MMMM

答案 2 :(得分:2)

没有预定义的格式来实现这一目标。以下是一种解决方法:使用java.text.DateFormat.SHORT格式化日期,并使用格式为yyyy的自定义格式化程序。现在为后者搜索前者的结果。

如果年份接近开头,则删除年后的下一个非数字,否则在年份之前删除非数字。

但这也不完美,因为它给你“12.3”而不是“12.3”。对于德国人。

如果你真的需要做对,请查看Java源代码,特别是sun.text.resources中的包rt.jar并打印所有语言环境日期(您只需创建一个DateFormat所有语言环境都使用SHORT类型。

这应该为您提供创建自己的资源包所需的所有数据,其中包含所有语言的日/月格式字符串。

答案 3 :(得分:1)

您可以提取模式并删除年份。

SimpleDateFormat df = (SimpleDateFormat)
                      DateFormat.getDateInstance(DateFormat.SHORT);
String pattern = df.toLocalizedPattern().replaceAll(".?[Yy].?", "");
System.out.println(pattern);
SimpleDateFormat mdf = new SimpleDateFormat(pattern);

打印

M/d

在我的系统上。

答案 4 :(得分:1)

其他作者已经正确认识到Java平台没有为一个月 - 日组合管理预定义的本地化格式模式而没有使用年份,因此建议使用数据分析和正则表达式模式等复杂的解决方法。

我已根据最新的CLDR数据将此类格式模式嵌入到我的库Time4J中。例如:

AnnualDate now = SystemClock.inLocalView().now(AnnualDate.chronology());
System.out.println("xml-schema: " + now); // --09-23

ChronoFormatter<AnnualDate> fEnglishUS =
    ChronoFormatter.ofStyle(DisplayMode.SHORT, Locale.US, AnnualDate.chronology());
ChronoFormatter<AnnualDate> fFrench =
    ChronoFormatter.ofStyle(DisplayMode.SHORT, Locale.FRENCH, AnnualDate.chronology());
ChronoFormatter<AnnualDate> fGerman =
    ChronoFormatter.ofStyle(DisplayMode.SHORT, Locale.GERMAN, AnnualDate.chronology());
System.out.println("us: " + fEnglishUS.format(now)); // 9/23
System.out.println("french:  " + fFrench.format(now)); // 23/09
System.out.println("german:  " + fGerman.format(now)); // 23.9.

很高兴知道:ICU4J确实具备此功能,但API功能要复杂得多。

答案 5 :(得分:0)

您可能已经意识到,短格式不仅取决于语言,还取决于国家/地区。不幸的是,Java中没有内置的模式。相反,您可能需要使用CLDR定义的那些 - 搜索“模式”或“Md”(月/日模式)。

但是,我必须警告你,这些模式可能是错误的。相反,您可能希望将它们移动到资源文件中并让翻译人员处理它们(适当的评论它是什么以及如何处理它。)

答案 6 :(得分:0)

LocalDate ld = LocalDate.parse( "2012-12-03" ); // December 3rd. MonthDay md = MonthDay.from( ld );

Java提供了一个类来表示没有任何年份的这样的值,月份和日期:java.time.MonthDay

--MM-DD

ISO 8601

如果您致电toString,则会获得以ISO 8601标准--MMDD之后的格式生成的字符串。这是扩展格式,标准还允许使用基本格式最小化分隔符String output = md.toString(); 的使用。参考:第5.2.1.3节截断的表示d)ISO 8601:2000标准的隐含年份中的特定日期。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd" );
String output = md.format( f ); 
  

- 12-03

自定义格式

我建议尽可能使用标准格式。但是,如果必须使用其他格式,则可以使用DateTimeFormatter类进行指定。

Y
  

12/03

java.time类提供date-only valuesdate-time values的自动本地化。不幸的是,没有对月日价值的支持。因此,您必须明确定义自己的自定义格式,以实现所需的本地化。有关替代方案,请参阅the Answer by Meno Hochschild

答案 7 :(得分:0)

有关在设置为西班牙语区域设置的设备上使用 DateFormat.getDateInstance(DateFormat.LONG)DateFormat.getDateInstance(DateFormat.FULL) 的说明。

来自 simpleDateFormat.toLocalizedPattern() 的文本文字的格式。

d 'de' MMMM 'de' y

在我正在看的情况下。

e.g. 2021 年 1 月 15 日在西班牙语中是 15 de enero de 2021

删除 y 和任何非单词字符会导致 java.lang.IllegalArgumentException: Unterminated quote 异常(因为最后一个 ' 上的最后一个 'de' 将作为非单词字符被删除) .

因此,作为最糟糕的解决方案,在我们的非年份格式化程序中,如果模式包含单引号字符 ',我们将删除任何文字。 (使用正则表达式 pattern.replaceAll("'\\w+'", ""))。

我已经与其他一些当地人进行了测试,它似乎有效。 (de, ja, pt, en)