SimpleDateFormat 返回带有前导零的日期,例如 0022 Feb 2018

SimpleDateFormat is returning date with leading zeros like 0022 Feb 2018

这是我的 SimpleDateFormat 实例:

public static final SimpleDateFormat DD_MMM_YYYY =
                new SimpleDateFormat("dd MMM yyyy");

我正在将以毫秒为单位的时间戳转换为这种日期格式。

有时 returns 正确的日期如下:

22 Feb 2018

但有时(在极少数情况下)returns 日期不正确,例如:

0022 Feb 2018

为什么要添加两个前导零?

我的方法如下-

public static String convertLongToDate(long timestamp) {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        long todaysTimestamp = calendar.getTimeInMillis();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        long yesterdayTimestamp = calendar.getTimeInMillis();
        calendar.setTimeInMillis(timestamp);
        String timeString;

        String todaysDateStr = DD_MMM_YYYY.format(todaysTimestamp);
        String givenDateStr = DD_MMM_YYYY.format(calendar.getTimeInMillis());

        Log.d("Check", "date-> todaysDateStr=" + todaysDateStr + ", givenDateStr=" + givenDateStr+", todayLength="+todaysDateStr.length()+", givenLength="+givenDateStr.length());
        if (todaysDateStr.equalsIgnoreCase(givenDateStr)) {
            timeString = AppConstants.TODAY;
        } else if (DD_MMM_YYYY.format(yesterdayTimestamp).equalsIgnoreCase(givenDateStr)) {
            timeString = AppConstants.YESTERDAY;
        } else {
            timeString = givenDateStr;
        }
        timeString = timeString.trim();
        return timeString;
    }

没有关于您如何使用格式化程序的更多信息,很难判断问题出在哪里。

但我猜这是因为 SimpleDateFormat 不是 thread-safe。

当 运行 它处于 multi-thread 环境中时,奇怪的事情开始发生。只需查看 google,您就会发现很多相关文章:https://www.google.com/search?q=simpledateformat+not+thread+safe

更新:

使用你的代码,我无法重现问题,但我仍然认为它与在多线程环境中使用 non-threadsafe class 有关 - 这是我所知道的唯一问题这可能会发生,特别是 "sometimes" 因素。

愚蠢的问题: 是否有任何 AppConstants 值有前导零?随便问问,谁知道...

备选方案

您可以为此使用更好的 API,例如 ThreeTen Backport:

有了它,您的代码变得更加清晰易懂 understand/maintain:

public static String convertLongToDate(long timestamp) {
    DateTimeFormatter f = DateTimeFormatter.ofPattern("dd MMM yyyy");
    ZonedDateTime today = ZonedDateTime.now(ZoneId.systemDefault());
    ZonedDateTime yesterday = today.minusDays(1);

    ZonedDateTime givenDate = Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault());

    String timeString;
    // compare just the date (day, month, year)
    // no need to convert to string to compare if dates are the same
    if (today.toLocalDate().equals(givenDate.toLocalDate())) {
        timeString = AppConstants.TODAY;
    } else if (yesterday.toLocalDate().equals(givenDate.toLocalDate())) {
        timeString = AppConstants.YESTERDAY;
    } else {
        timeString = givenDate.format(f);
    }
    timeString = timeString.trim();
    return timeString;
}

这个 API 是线程安全的,SimpleDateFormat 有时会发生的奇怪事情在这里不会发生。

或者,如果你不想使用另一个API,你可以使用这个post的解决方案:http://fahdshariff.blogspot.com.br/2010/08/dateformat-with-multiple-threads.html

如果您显示当前日期和特定格式,则使用下面的代码。

Date c = Calendar.getInstance().getTime(); // get current date and time.
    System.out.println("Current time => " + c);

    SimpleDateFormat df = new SimpleDateFormat("dd MMM yyyy"); // define your format.
    String formattedDate = df.format(c);
    System.out.println("New Date To Show::"+formattedDate);