aboutsummaryrefslogblamecommitdiff
path: root/app/src/main/java/com/camilstaps/common/Date.java
blob: 455c4ac01b3213dc03d4d0389d3fbc491dcc440f (plain) (tree)
1
2
3
4
5
6
7
8
                              
                               
 
                                
                                  
                          
                                   


                               

                      



                                               

                                                                         





                                              




                                                 




                                               



                                                         










                                                              


                       
















                            


                               


                                 


                                    


                                      



                                                             








                                     



                                                             








                                       



                                                             








                                       



                                                             








                                     


                                                            






                                          



                                     








                                                


                                           


                                 



                                        


                                            


                                           


                                




                                         













                                                        


                                            


                                        



                                                                            





















                                         
                                                       
                                   
                                                         
                               
                                                     

                 




                                                                              



                                               












                                                                                
                                                 
                                                                                 



                                                                                                    
     
package com.camilstaps.common;

import android.content.Context;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Date
 *
 * @author Camil Staps
 */
public class Date implements Comparable<Date> {

    private int year, month, day;

    /**
     * Constructor without parameters creates a Date for the current date
     */
    public Date() {
        Calendar cal = Calendar.getInstance();
        year = cal.get(Calendar.YEAR);
        month = cal.get(Calendar.MONTH) + 1;
        day = cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * Constructor to specify year, month and day
     * @param year
     * @param month
     * @param day
     */
    public Date(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    /**
     * Constructor to parse a Date from a String
     * @param format the String in YYYY-mm-dd format
     * @throws ParseException if the format was incorrect
     */
    public Date(String format) throws ParseException {
        Pattern pat = Pattern.compile("(\\d*)-(\\d*)-(\\d*)");
        Matcher match = pat.matcher(format);
        if (match.find()) {
            year = Integer.parseInt(match.group(1));
            month = Integer.parseInt(match.group(2));
            day = Integer.parseInt(match.group(3));
        } else {
            throw new ParseException("Wrong date format", 0);
        }
    }

    /**
     * Copy-constructor
     * @param copy
     */
    public Date(Date copy) {
        year = copy.year;
        month = copy.month;
        day = copy.day;
    }

    public int getYear() {
        return year;
    }

    public int getMonth() {
        return month;
    }

    public int getDay() {
        return day;
    }

    /**
     * Add some amount of years
     * @param n
     */
    public void addYears(int n) {
        year += n;
    }

    /**
     * Subtract some amount of years
     * @param n
     */
    public void subtractYears(int n) {
        year -= n;
    }

    /**
     * Add some amount of months
     * @param n
     * @todo This could be optimized by removing the for loop
     */
    public void addMonths(int n) {
        for (int i = 0; i < n; i++) {
            month++;
            if (month >= 13) {
                month = 1;
                addYears(1);
            }
        }
    }

    /**
     * Subtract some amount of months
     * @param n
     * @todo This could be optimized by removing the for loop
     */
    public void subtractMonths(int n) {
        for (int i = 0; i < n; i++) {
            month--;
            if (month <= 0) {
                month = 12;
                subtractYears(1);
            }
        }
    }

    /**
     * Add some amount of days
     * @param n
     * @todo This could be optimized by removing the for loop
     */
    public void addDays(int n) {
        for (int i = 0; i < n; i++) {
            day++;
            if (day >= daysOfMonth()) {
                day = 1;
                addMonths(1);
            }
        }
    }

    /**
     * Subtract some amount of days
     * @param n
     * @todo This could be optimized by removing the for loop
     */
    public void subtractDays(int n) {
        for (int i = 0; i < n; i++) {
            day--;
            if (day <= 0) {
                month--;
                day = daysOfMonth();
            }
        }
    }

    /**
     * Add (if n>0) or subtract (if n<0) some amount of days
     * @param n
     */
    public void addOrSubtractDays(int n) {
        if (n < 0) {
            subtractDays(-n);
        } else {
            addDays(n);
        }
    }

    /**
     * Check if a year is a leap year
     * @param year
     * @return
     */
    public static boolean isLeapYear(int year) {
        if (year % 4 != 0)
            return false;
        if (year % 100 != 0)
            return true;
        if (year % 400 != 0)
            return false;
        return true;
    }

    /**
     * Check if this date is in a leap year
     * @return
     */
    public boolean isLeapYear() {
        return isLeapYear(year);
    }

    /**
     * Give the number of days in a year
     * @param year
     * @return
     */
    public static int daysOfYear(int year) {
        return isLeapYear(year) ? 366 : 365;
    }

    /**
     * Give the number of days in this year
     * @return
     */
    public int daysOfYear() {
        return daysOfYear(year);
    }

    /**
     * Give the number of days in a month
     * @param year
     * @param month
     * @return
     */
    public static int daysOfMonth(int year, int month) {
        switch (month) {
            case 2: return isLeapYear(year) ? 29 : 28;
            case 1:
            case 3:
            case 5:
            case 8:
            case 10:
            case 12:
                return 31;
            default:
                return 30;
        }
    }

    /**
     * Give the number of days in this month
     * @return
     */
    public int daysOfMonth() {
        return daysOfMonth(year, month);
    }

    /**
     * Give the (absolute value of the) difference in days with another Date
     * @param withDate
     * @return
     */
    public int diffDays(Date withDate) {
        Date smaller, bigger;
        if (compareTo(withDate) > 0) {
            smaller = new Date(this);
            bigger = new Date(withDate);
        } else {
            smaller = new Date(withDate);
            bigger = new Date(this);
        }
        if (smaller.equals(bigger)) {
            return 0;
        }
        int i = 0;
        while (!smaller.equals(bigger)) {
            smaller.addDays(1);
            i++;
        }
        return i;
    }

    @Override
    public int compareTo(Date another) {
        if (another.year != year)
            return compareIntegers(another.year, year);
        if (another.month != month)
            return compareIntegers(another.month, month);
        if (another.day != day)
            return compareIntegers(another.day, day);
        return 0;
    }

    /**
     * Integer.compare was added in API level 19, so this is for compatibility
     * @param x
     * @param y
     * @return
     */
    private int compareIntegers(int x, int y) {
        if (x == y) return 0;
        return (x < y) ? -1 : 1;
    }

    /**
     * Check if two objects represent the same date
     * @param date
     * @return
     */
    public boolean equals(Date date) {
        return year == date.year && month == date.month && day == date.day;
    }

    /**
     * Present the date in a 'nice' String, according to the user's localization
     * @param context
     * @return
     */
    public String toNiceString(Context context) {
        SimpleDateFormat sdf = new SimpleDateFormat("EEEE d MMMM y");
        return sdf.format(new GregorianCalendar(year, month - 1, day).getTime());
    }

    @Override
    public String toString() {
        return Integer.toString(year) + "-" + Integer.toString(month) + "-" + Integer.toString(day);
    }
}