4
\$\begingroup\$

The following is my sample code:

String month = "09";

String year = "2014";

String monthYear = "092014";

The monthYear format is MMyyyy, I wish to format it to become MMyy. Thus, I am doing it as follows:

Method 1:

final SimpleDateFormat oriMonthYear = new SimpleDateFormat( "MMyyyy" );
final SimpleDateFormat changeMonthYear = new SimpleDateFormat( "MMyy" );

String newMonthYear = changeMonthYear.format( oriMonthYear.parse( month + year) );

This give me correct output, but I am not sure am I doing it by stupid way or not. I believe it should be another best practice and smart to way to do it.

\$\endgroup\$
2
  • \$\begingroup\$ That's pretty much it as far as using Java's libraries. Though, that month + year is suspect... You're better off using Joda. \$\endgroup\$ Jan 26 '15 at 4:33
  • \$\begingroup\$ [All information for datatime you have. ](docs.oracle.com/javase/7/docs/api/java/text/…) \$\endgroup\$
    – Ibrahim
    Jan 26 '15 at 15:45
2
\$\begingroup\$

We can use YearMonth in Java 8 or later like below:

YearMonth
        .parse(yearMonth, DateTimeFormatter.ofPattern(MMYYYY))
        .format(DateTimeFormatter.ofPattern(MMYY));
\$\endgroup\$
2
  • \$\begingroup\$ "MMyyyy" or where do the constants arrive from? \$\endgroup\$
    – Joop Eggen
    Nov 11 '21 at 10:12
  • \$\begingroup\$ Got my vote though: the new date time class is also usefull for working with YearMonths. And in modular java one need no SimpleDateFormat in ones application. \$\endgroup\$
    – Joop Eggen
    Nov 11 '21 at 10:16
1
\$\begingroup\$

Use Java's THreadLocal type to wrap your SimpleDateFormat objects.

ThreadLocal<SimpleDateFormat> oriFormatHolder = new ThreadLocal<SimpleDateFormat>() {

    @Override
    protected SimpleDateFormat initialValue() {
        return new SimpleDateFormat("MMyyyy");
    }
};


final SimpleDateFormat oriMonthYear = oriFormatHolder.get();

The reason for this is because SimpleDateFormat is not thread safe.

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

Read more here

I actually ran into this problem. In a multi threaded env we were sharing a SimpleDateFormat object across many threads and started getting bad results. By wrapping it with ThreadLocal the problem went away.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ An explanation why do this would be nice! \$\endgroup\$
    – janos
    Jan 26 '15 at 6:31
  • \$\begingroup\$ Rather, do not use ThreadLocal. It's a wonderful way to shoot yourself in the knee if you don't know what you're doing. \$\endgroup\$ Jan 26 '15 at 14:19
  • 1
    \$\begingroup\$ @janos, I updated my answer with the reason why. \$\endgroup\$ Jan 26 '15 at 14:24
0
\$\begingroup\$

If you are assured that the Strings you get form a valid date then you can just remove the first and second characters from the year string.

String newMonthYear = month + year.substring(2);
\$\endgroup\$
0
\$\begingroup\$

Do you want to change your date format in the future?

Do you always receive correct input?

Do you reformat dates in a performance-sensitive context?

If it is "No", "Yes" and "Yes" you're better off with String.format and substring to do what you want. Otherwise, SimpleDataFormat is the way to go (don't forget synchronization).

The way you use SimpleDataFormat is perfectly correct (sans the string concatenation part), it's just more expensive resource-wise (to pay off for it being much more powerful tool).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.