joan
joan

Reputation: 131

converting date to GregorianCalendar Date format

I want to convert the org.joda.time.LocalDate object to java.util.GregorianCalendar. java.util.GregorianCalendar month displayed from index 0 to 11. So October is represented with digit 9 , November with digit 10....Whereas for LocalDate October is represented with digit 10, november with 11....

I am working on existing application where they have used GregorianCalendar. Now I want to convert my LocalDate value which I had received through a method call into GregorianCalendar format so that month values are matched.

I have already searched many blogs but could not convert the value. Below is the code I tried but still could not able to change the date format to GregorianCalendar format.

java code:

import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
class Convert{
    public static String format(GregorianCalendar calendar){
        SimpleDateFormat fmt = new SimpleDateFormat("dd-M-yyyy");
        fmt.setCalendar(calendar);
        String dateFormatted = fmt.format(calendar.getTime());
        System.out.println("--date formatted--- " + dateFormatted);
        return dateFormatted;
    }
    void convertLocalDateToGregorianCalendar(){
        LocalDate localDate = new LocalDate();
        DateTime dateTimeObj = localDate.toDateTimeAtStartOfDay();
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTimeInMillis(dateTimeObj.getMillis());
        String formattedGCDate = format(gc);
        System.out.println("converted LocalDate to GregorianDate date value " + formattedGCDate);
    }
    public static void main(String[] args) {
                new Convert().convertLocalDateToGregorianCalendar();         
} }

Output:

--date formatted--- 13-10-2016
converted LocalDate to GregorianDate date value 13-10-2016

Expected date value in the output: 13-9-2016 (As for GregorianCalendar October month is represent with digit 9).

PS: java5 is the version I am using.

Upvotes: 1

Views: 17453

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 338664

tl;dr

java.util.GregorianCalendar.from( 
    java.time.LocalDate.parse( myJodaLocalDate.toString() )
    .atStartOfDay( ZoneId.of( "America/Montreal" ) )
)

Details

You are mixing two very different date-time libraries:

  • Joda-Time
  • legacy date-time classes bundled with Java

The old legacy date-time classes are poorly-designed, confusing, and troublesome; avoid them. Supplanted by the java.time classes.

The Joda-Time project is excellent, and provided the inspiration for java.time. But now the project is in maintenance mode, with the team advising migration to the java.time classes.

java.time

Convert your org.joda.time.LocalDate to a java.time.LocalDate by going through a String. Both use standard ISO 8601 formats by default, so no need to specify a formatting pattern.

java.time.LocalDate ld = java.time.LocalDate.parse( myJodaLocalDate.toString() );

You apparently want a date-time value, so we need to add a time-of-day to your date-only LocalDate. Apparently you want to go with the first moment of the day. Do not assume this first moment is 00:00:00 as anomalies such as Daylight Saving Time (DST) may mean another time such as 01:00:00. Let java.time determine the moment. You need to specify your desired/expected time zone to account for such anomalies and to adjust the wall-clock time.

The code in your Question ignores this crucial issue of time zone. If ignored, your JVM’s current default time zone is implicitly applied. This default can change at any moment during runtime. So better to be explicit.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ld.atStartOfDay( z );

I strongly suggest you stick with the java.time classes. But if you absolutely need the old legacy classes, such as for interfacing with old code not yet updated to java.time, then you may convert. Look to new methods added to the old classes.

GregorianCalendar gc = java.util.GregorianCalendar.from( zdt );

Month indexing

The Question asks for how to generate a String with the month number as an zero-based index 0-11 for January to December, to match how GregorianCalendar works internally.

Frankly, answering that would be a disservice. Numbering months with a zero-based number is crazy nuts insane. Doing so would cause no end of confusion. Doing so in GregorianCalendar was an extremely poor design choice to begin with. It's use should be extinguished rather than promoted.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to java.time.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

  • Java SE 8 and SE 9 and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Upvotes: 1

Ramachandran.A.G
Ramachandran.A.G

Reputation: 4948

If i understand the question right we are mixing 2 things

a) Internal representation of the months within Calender / GregorianCalender and the actual Calendar itself.

The internal representation as you rightly say is represented from 0-11 denoting 12 months of the year , the human interpretation of that is 1-12 months of the year. When you call the format operation you get the way the date appears on a actual human calender which is October , month 10 of the year. The internal representation is still 9. If you ask how , you can check using the API

gc.setTimeInMillis(dateTimeObj.getMillis());
System.out.println(gc.get(Calendar.MONTH));

This prints the numeral 9

If you want the internal representation of the date , you can do so too. A really hacky way would be as follows although i do not vouch for it , but gives you an overall idea of things.

LocalDate localDate = new LocalDate();
DateTime dateTimeObj = localDate.toDateTimeAtStartOfDay();
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(dateTimeObj.getMillis());
System.out.println(gc.get(Calendar.DAY_OF_MONTH) +"-"+ ("00"+ gc.get(Calendar.MONTH)).substring(1)  +"-"+gc.get(Calendar.YEAR));

Upvotes: 1

Viet
Viet

Reputation: 3409

I think you can't directly use SimpleDateFormat to format Gregorian date. I have two suggestions work around:

1.If you don't care to reuse the calendar.getTime() you can roll (or add) the month by -1 before fmt.format:

SimpleDateFormat fmt = new SimpleDateFormat("dd-M-yyyy");
fmt.setCalendar(calendar);    
calendar.roll(Calendar.MONTH, -1); //or add
String dateFormatted = fmt.format(calendar.getTime());
System.out.println("--date formatted--- " + dateFormatted);

2.Don't use SimpleDateFormat, calendar.get(Calendar.MONTH) will return 9 as your expect:

public static String format(GregorianCalendar calendar){
    String dateFormatted = String.format("%s-%s-%s", calendar.get(Calendar.DATE),
                            calendar.get(Calendar.MONTH), calendar.get(Calendar.YEAR));
    System.out.println("--date formatted--- " + dateFormatted);
    return dateFormatted;
}

Upvotes: 1

Related Questions