Format date without year

前端 未结 10 1524

How can create text representation of some date, that takes locale into account and contains only day and month (no year)?

Following code gives me s

相关标签:
10条回答
  • 2020-12-25 13:08

    If you use Android, you might be able to use getBestDateTimePattern , and just put there all the fields you want to allow. It should automatically put the correct order and special characters according to the current locale.

    Sadly, it requires API 18+ .

    EDIT: This seems like a not-so-good choice, sadly. I've written about it here: http://code.google.com/p/android/issues/detail?id=171591


    So, this is what I've done:

    public static String convertDateToString(Context context, Locale locale, final Date date, boolean alsoShowYearIfPossible) {
        if (date == null)
            return "";
        String defaultDateFormat;
        if (locale != null) {
            defaultDateFormat = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale)).toLocalizedPattern();
        } else defaultDateFormat = getDefaultDateFormat(context);
        if (alsoShowYearIfPossible)
            return new SimpleDateFormat(defaultDateFormat, Locale.getDefault()).format(date);
        //need removal of year
        String removedYearFormat = defaultDateFormat.replaceAll("[^{mdMD}]*y+[^{mdMD}]*", "");
        String result = new SimpleDateFormat(removedYearFormat, Locale.getDefault()).format(date);
        //Log.d("AppLog", locale + ": \"" + defaultDateFormat + "\" => \"" + removedYearFormat + "\" =>" + result);
        return result;
    }
    
    private static String getDefaultDateFormat(final Context context) {
        String dateFormatString = Settings.System.getString(context.getContentResolver(), Settings.System.DATE_FORMAT);
        if (TextUtils.isEmpty(dateFormatString)) {
            // if device date format is available , use device date order,and if not available ,use default
            final char[] dateFormatOrder = android.text.format.DateFormat.getDateFormatOrder(context);
            if (dateFormatOrder.length == 0)
                dateFormatString = DEFAULT_DATE_FORMAT;
            else {
                // construct the date format based on the device date order
                final StringBuilder sb = new StringBuilder();
                for (int i = 0; i < dateFormatOrder.length; ++i) {
                    final char c = dateFormatOrder[i];
                    switch (Character.toLowerCase(c)) {
                        case 'y':
                            sb.append("yyyy");
                            break;
                        case 'm':
                            sb.append("MM");
                            break;
                        case 'd':
                            sb.append("dd");
                            break;
                    }
                    if (i != dateFormatOrder.length - 1)
                        sb.append('-');
                }
                dateFormatString = sb.toString();
            }
        }
        return dateFormatString;
    }
    

    This code works on any locale available, on Android 5.0.2 .

    Here's a sample of how to check it on on locales:

        Date date = new Date();
        for (Locale locale : Locale.getAvailableLocales()) {
            SimpleDateFormat sdf = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale);
            String localizedDatePattern = sdf.toLocalizedPattern();
            convertDateToString(this,locale,date,false);
        }
    
    0 讨论(0)
  • Using com.ibm.icu library:

    import com.ibm.icu.text.DateFormat;
    
    DateFormat.getPatternInstance(DateFormat.MONTH_DAY, locale).format(date);
    
    0 讨论(0)
  • 2020-12-25 13:15

    The main difficulty here is that in some locales the order of month and day is different. I solved it in a way which is different from those which presented here.

        Date dateObject = ...;
    
        String dayMonthDateString = getDayMonthDateString(dateObject, Locale.GERMANY);
        Log.i("customDate", "dayMonthDateString = " + dayMonthDateString);
    
    private String getDayMonthDateString(Date date, Locale locale)
    {
        try
        {
            boolean dayBeforeMonth = defineDayMonthOrder(locale);
    
            SimpleDateFormat newDateFormat;
    
            if (dayBeforeMonth)
            {
                newDateFormat = new SimpleDateFormat("dd/MM", locale);
            }
            else
            {
                newDateFormat = new SimpleDateFormat("MM/dd", locale);
            }
    
            return newDateFormat.format(date);
        }
        catch (ParseException e)
        {
            e.printStackTrace();
        }
    
        return null;
    }
    
    
    private boolean defineDayMonthOrder(Locale locale) throws ParseException
    {
        String day = "10";
        String month = "11";
        String year = "12";
    
        String calendarDate = day + "." + month + "." + year;
    
        SimpleDateFormat format = new SimpleDateFormat("dd.MM.yy");
        Date date = format.parse(calendarDate);
    
        String localizedDate = SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT, locale).format(date);
    
        int indexOfDay = localizedDate.indexOf(day);
        int indexOfMonth = localizedDate.indexOf(month);
    
        return indexOfDay < indexOfMonth;
    }
    
    0 讨论(0)
  • 2020-12-25 13:21

    Although Andrzej Pronobis's answer is very good, it doesn't work for instance with ZH local. I ended up with manual removing year from localized pattern. This function was tested for all locals for SHORT, MEDIUM, LONG and FULL formats.

    public String removeYearFromPattern(String pattern) throws IllegalArgumentException {
        int yPos = 0;
        while (yPos < pattern.length() && pattern.charAt(yPos) != 'y' && pattern.charAt(yPos) != 'Y') {
            if (pattern.charAt(yPos) == '\'') {
                yPos++;
                while (yPos < pattern.length() && pattern.charAt(yPos) != '\'') yPos++;
            }
            yPos++;
        }
        if (yPos >= pattern.length()) throw new IllegalArgumentException("Did not find year in pattern");
        String validPatternLetters = "EMd";
        // go forward
        int endPos = yPos;
        while (endPos < pattern.length() && validPatternLetters.indexOf(pattern.charAt(endPos)) == -1) {
            endPos++;
            if (endPos < pattern.length() && pattern.charAt(endPos) == '\'') {
                endPos++;
                while (endPos < pattern.length() && pattern.charAt(endPos) != '\'')
                    endPos++;
            }
        }
        if (endPos != pattern.length()) validPatternLetters += ',';
        // go backward
        int startPos = yPos;
        while (startPos >= 0 && validPatternLetters.indexOf(pattern.charAt(startPos)) == -1) {
            startPos--;
            if (startPos >= 0 && pattern.charAt(startPos) == '\'') {
                startPos--;
                while (startPos >= 0 && pattern.charAt(startPos) != '\'') startPos--;
            }
        }
        startPos++;
        String yLetters = pattern.substring(startPos, endPos);
        return pattern.replace(yLetters, " ").trim();
    }
    

    Function above can be tested by running:

    for (Locale locale : Locale.getAvailableLocales()) {
        SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.FULL, locale);
        String dfPattern = "?";
        String newPattern = "?";
        try {
            dfPattern = df.toPattern();
            newPattern = removeYearFromPattern(dfPattern);
            df.applyPattern(newPattern);
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Error removing year for " + locale + ": " + e.getMessage());
        }
        Log.d(TAG, locale + ": old  " + dfPattern + "; new " + newPattern + "; result " + df.format(new Date()));
    }
    

    I know it is not as elegant as regex, but it is a little bit faster and works for all locals (if I am able to recognize).

    0 讨论(0)
提交回复
热议问题