import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class GregorianCalendar1 {

    private static void prt() {
        System.out.println();
    }
    private static void prt(String s) {
        System.out.println(s);
    }

    public static void main(String[] args) {

        //Create a GregorianCalendar object

        prt("Create and print a Gregorian Calendar object");
        prt("===============================================================");
        GregorianCalendar c1 = new GregorianCalendar();   //create a GregorianCalendar obj
        prt(c1 + "");                                     //print all the fields                           
        prt();

        prt("Calendar current date and time, & milliseconds since 1/1/1970");
        prt("===============================================================");
        Date now = c1.getTime();                          //returns a Date object
        prt("c1.getTime()          : " + now);
        prt();
        long milliSec = c1.getTimeInMillis();             //returns a long
        prt("c1.getTimeInMillis()  : " + milliSec);
        prt();

        datePrint(c1);
        
        
        //To create a GregorianCalendar object for a different date/time
        //param: year,month,day,hour24,min,sec as integers
        //       month is 0 based :(
 
        prt("Create a Calendar obj and change it using set() methods");
        prt("===============================================================");
        GregorianCalendar c2 = new GregorianCalendar(2018,0,15, 14,0,0);    //15/01/2018 14:00:00                   
        prt("c2.getTime()          : " + c2.getTime());
        prt();
        prt("c2.getTimeInMillis()  : " + c2.getTimeInMillis());
        prt();

        datePrint(c2);


        //Set a GregorianCalendar to different values
 
        prt("Create a Calendar obj and use set() method to set date fields");
        prt("===============================================================");
        GregorianCalendar c3 = new GregorianCalendar();                   
        c3.set(Calendar.YEAR,      2019);                                        
        c3.set(Calendar.MONTH,        0);                        //January (0 based)                                      
        c3.set(Calendar.DATE,        22);                                        
        c3.set(Calendar.HOUR_OF_DAY, 16);                        //24 hour clock                                  
        c3.set(Calendar.MINUTE,       0);
        c3.set(Calendar.SECOND,       0);
        prt("c3.getTime()          : " + c3.getTime());
        prt();
        prt("c3.getTimeInMillis()  : " + c3.getTimeInMillis());
        prt();
        
        datePrint(c3);


        //Compare 2 calendars.  Result: 0=equal, -1=smaller, 1=larger

        prt("Compare 2 calendars.  Result: 0=equal, -1=smaller, 1=larger");
        prt("======================================================================");
        int x = c1.compareTo(c2);
        prt("GregorianCalendar c1....: " + c1.getTime());   //getTime() returns a Date  obj. 
        prt("GregorianCalendar c2....: " + c2.getTime()); 
        prt("c1 compareTo() c2 is....: " + x);              //c1 is greater than c2, prints 1
        prt();


        //Is a given year a leap year?

        prt("Is a given year a leap year?");
        prt("======================================================================");
        int year       = c1.get(Calendar.YEAR);
        boolean isLeap = c1.isLeapYear(year);
        prt("GregorianCalendar c1....: " + c1.getTime());   
        prt("Leap year?..............: " + isLeap); 
        prt();


        //Compute the number of days between 2 days
 
        prt("Number of Days in between calendar1 and calendar2");
        prt("===============================================================");
        float diff = dateDiff(c1, c2);
        prt("Num of days in between: " + diff);
        prt();


        //Add (or subtract) an number from a Calendar date

        prt("Add a Unit (YEAR,MONTH,DAY,HOUR,MINUTE,SECOND) to Calendar date");
        prt("===============================================================");
        GregorianCalendar c4 = dateAdd(c1, Calendar.MONTH, 2);
        prt("today + 2 months      : " + c4.getTime());
        prt();
     }

    //--------------------------------------------------------------------------------------------------
    //Print all Calendar Fields
    //--------------------------------------------------------------------------------------------------
    public static void datePrint(GregorianCalendar c)
    {
        prt("Calendar fields");
        prt("===============================================================");
        int date         = c.get(Calendar.DATE);
        int month        = c.get(Calendar.MONTH);               //month 0-11
        int year         = c.get(Calendar.YEAR); 
        int hour         = c.get(Calendar.HOUR);                //hours 1-12
        int hour24       = c.get(Calendar.HOUR_OF_DAY);         //hours 0-23
        int minute       = c.get(Calendar.MINUTE);
        int second       = c.get(Calendar.SECOND);
        int milliSecond  = c.get(Calendar.MILLISECOND);
        int am_pm        = c.get(Calendar.AM_PM);
        int day_of_week  = c.get(Calendar.DAY_OF_WEEK);         //1-7, 1=Sunday
        int julian_day   = c.get(Calendar.DAY_OF_YEAR);
        int week_of_year = c.get(Calendar.WEEK_OF_YEAR);
        int week_of_mth  = c.get(Calendar.WEEK_OF_MONTH);
        int zone_offset  = c.get(Calendar.ZONE_OFFSET);
        String day_name  = dayName(c);                          //call dayName method below
        String mth_name  = mthName(c);                          //call mthName method below  
         
        prt("DATE                  : " + date);
        prt("MONTH (0-based)       : " + month);
        prt("YEAR                  : " + year);
        prt("HOUR                  : " + hour);
        prt("HOUR_OF_DAY (24-hour) : " + hour24);
        prt("MINUTE                : " + minute);
        prt("SECOND                : " + second);
        prt("MILLISECOND           : " + milliSecond);
        prt("AM_PM                 : " + am_pm);
        prt("DAY_OF_WEEK           : " + day_of_week);
        prt("DAY_OF_YEAR           : " + julian_day);
        prt("WEEK_OF_YEAR          : " + week_of_year);
        prt("WEEK_OF_MONTH         : " + week_of_mth);
        prt("ZONE_OFFSET           : " + zone_offset);
        prt("*Day Name             : " + day_name);
        prt("*Month Name           : " + mth_name);
        prt();
    }

    //--------------------------------------------------------------------------------------------------
    //Determine the day_name from the day_of_week number
    //--------------------------------------------------------------------------------------------------
    public static String dayName(GregorianCalendar c)
    {
        String[] days   = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
        int day_of_week = c.get(Calendar.DAY_OF_WEEK);
        String day_name = days[day_of_week-1];                          //day_of_week 1-7, array 0 based
        return(day_name);
    }

    //--------------------------------------------------------------------------------------------------
    //Determine the month_name from the month number
    //--------------------------------------------------------------------------------------------------
    public static String mthName(GregorianCalendar c)
    {
        String[] mths   = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
        int month       = c.get(Calendar.MONTH);
        String mth_name = mths[month];                                  //month 0-11, OK for array indexing 
        return(mth_name);
    }

    //--------------------------------------------------------------------------------------------------
    //Determine the number of days in between 2 gregorian calendar dates
    //--------------------------------------------------------------------------------------------------
    public static float dateDiff(GregorianCalendar c1, GregorianCalendar c2)
    {
        long oneDay    = 24*60*60*1000;
        long milliSec1 = c1.getTimeInMillis(); 
        long milliSec2 = c2.getTimeInMillis(); 

        float diff     = (milliSec1 - milliSec2);   
              diff     = diff / oneDay;
                  
        return(diff);
    }                

    //--------------------------------------------------------------------------------------------------
    //Add or subtract a number of units to a Gregorian calendar date
    //unit = YEAR,MONTH,DAY,HOUR,MINUTE,SECOND,MILLISECOND 
    //--------------------------------------------------------------------------------------------------
    public static GregorianCalendar dateAdd(GregorianCalendar c, int unit, int amount) 
    {                                                           
        Object obj;
        GregorianCalendar cal;
    
        obj = c.clone();                                    //clone() returns an Object.
        cal = (GregorianCalendar) obj;                      //cast down to GregorianCalendar 
        cal.add(unit, amount);
                          
        return(cal);
    }                
}