All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pojava.datetime.Shift Maven / Gradle / Ivy

package org.pojava.datetime;


/**
 * Shift describes an offset in time in terms of CalendarUnit increments of various proportions.
 * Compare this to the "Duration" class, which describes fixed units of time in a self-contained
 * manner. A Shift, by contrast, may use a 23, 24 or 25 hour day depending on Daylight Saving
 * Time, or a 28, 29, 30, or 31 day month. The amount of time described by a Shift is dependent
 * on a start time and a time zone, both external to the Shift object itself.
 * 
 * @author John Pile
 * 
 */
public class Shift {
    /**
     * Nanoseconds per second
     */
    private static final long NPS = 1000000000;
    /**
     * Seconds per Minute
     */
    private static final long SPM = 60;
    /**
     * Minutes per Hour
     */
    private static final long MPH = 60;
    private int year = 0;
    private int month = 0;
    private int week = 0;
    private int day = 0;
    private int hour = 0;
    private int minute = 0;
    private int second = 0;
    private long nanosec = 0;
    
    public Shift() {
        // default constructor
    }

    /**
     * Constructor parsing from a string.
     * 
     * @param iso8601
     *            String representation of a duration.
     */
    public Shift(String iso8601) {
        char[] chars = iso8601.toCharArray();
        double accum = 0.0;
        double dec = 1.0;
        int sign = 1;
        int time = 0;
        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (c == '.') {
                dec /= 10;
            } else if (c == '-') {
                sign = -1;
            } else if (c >= '0' && c <= '9') {
                if (dec == 1.0) {
                    accum = accum * 10 + sign * dec * (c - '0');
                } else {
                    accum += sign * dec * (c - '0');
                    dec /= 10;
                }
            } else if (c == 'T') {
                time = 1;
            } else if (c == 'Y') {
                if (accum != 0) {
                    shiftYears(accum);
                    accum=0;
                    dec = 1;
                    sign = 1;
                }
            } else if (c == 'W') {
                if (accum != 0) {
                    shiftWeeks(accum);
                    accum=0;
                    dec = 1;
                    sign = 1;
                }
            } else if (c == 'D') {
                if (accum != 0) {
                    shiftDays(accum);
                    accum = 0;
                    dec = 1;
                    sign = 1;
                }
            } else if (c == 'H') {
                if (accum != 0) {
                    shiftHours(accum);
                    accum = 0;
                    dec = 1;
                    sign = 1;
                }
            } else if (c == 'M') {
                if (accum != 0) {
                    if (time==0) {
                        shiftMonths(accum);
                    } else {
                        shiftMinutes(accum);
                    }
                    accum = 0;
                    dec = 1;
                    sign = 1;
                }
            } else if (c == 'S') {
                if (accum != 0) {
                    shiftSeconds(accum);
                    accum = 0;
                    dec = 1;
                    sign = 1;
                }
            }
        }
    }

    public void shiftYears(double accum) {
        if (accum >= 1.0 || accum <= -1.0) {
            year += (long) accum;
            accum -= (long) accum;
        }
        if (accum != 0) {
            shiftMonths(accum * 12);
        }
    }
    
    public void shiftMonths(double accum) {
        if (accum >= 1.0 || accum <= -1.0) {
            month += (long) accum;
            accum -= (long) accum;
        }
        if (accum != 0) {
            shiftDays(accum * 30);
        }
    }
    
    public void shiftWeeks(double accum) {
        if (accum >= 1.0 || accum <= -1.0) {
            week += (long) accum;
            accum -= (long) accum;
        }
        if (accum != 0) {
            shiftHours(accum * 7);
        }
    }

    public void shiftDays(double accum) {
        if (accum >= 1.0 || accum <= -1.0) {
            day += (long) accum;
            accum -= (long) accum;
        }
        if (accum != 0) {
            shiftHours(accum * 24);
        }
    }

    public void shiftHours(double accum) {
        if (accum >= 1.0 || accum <= -1.0) {
            hour += (long) accum;
            accum -= (long) accum;
        }
        if (accum != 0) {
            shiftMinutes(accum * MPH);
        }
    }
    
    public void shiftMinutes(double accum) {
        if (accum >= 1.0 || accum <= -1.0) {
            minute += (long) accum;
            accum -= (long) accum;
        }
        if (accum != 0) {
            shiftSeconds(accum * SPM);
        }
    }
    
    public void shiftSeconds(double accum) {
        if (accum >= 1.0 || accum <= -1.0) {
            second += (long) accum;
            accum -= (long) accum;
        }
        if (accum != 0) {
            accum += (accum < 0 ? -0.0000000005 : 0.0000000005);
            nanosec += (long)(accum * 1000000000);
        }
    }

    private void settleContents() {
        if (nanosec >= NPS || nanosec <= -NPS) {
            long calcsec = nanosec / NPS;
            second += calcsec;
            nanosec -= calcsec * NPS;
        }
        if (second >= SPM || second <= -SPM) {
            long calcmin = second / SPM;
            minute += calcmin;
            second -= calcmin * SPM;
        }
        if (minute >= MPH || minute <= -MPH) {
            long calchour = minute / MPH;
            hour += calchour;
            minute -= calchour * MPH;
        }
    }

    public String toString() {
        // See ISO 8601
        settleContents();
        StringBuilder sb = new StringBuilder();
        sb.append('P');
        if (year != 0) {
            sb.append(year);
            sb.append('Y');
        }
        if (month != 0) {
            sb.append(month);
            sb.append('M');
        }
        if (week != 0) {
            sb.append(week);
            sb.append('W');
        }
        if (day != 0) {
            sb.append(day);
            sb.append('D');
        }
        if (hour != 0 || minute != 0 || second != 0 || nanosec != 0) {
            sb.append('T');
            if (hour != 0) {
                sb.append(hour);
                sb.append('H');
            }
            if (minute != 0) {
                sb.append(minute);
                sb.append('M');
            }
            if (second != 0 || nanosec != 0) {
                if (nanosec == 0) {
                    sb.append(second);
                } else {
                    sb.append((double)(second+nanosec/1000000000.0));
                }
                sb.append('S');
            }
        }
        return sb.toString();
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public int getWeek() {
        return week;
    }

    public void setWeek(int week) {
        this.week = week;
    }

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }

    public int getHour() {
        return hour;
    }

    public void setHour(int hour) {
        this.hour = hour;
    }

    public int getMinute() {
        return minute;
    }

    public void setMinute(int minute) {
        this.minute = minute;
        settleContents();
    }

    public int getSecond() {
        return second;
    }

    public void setSecond(int second) {
        this.second = second;
        settleContents();
    }

    public int getNanosec() {
        return (int) nanosec;
    }

    public void setNanosec(int nanosec) {
        this.nanosec = nanosec;
        settleContents();
    }

    public void setNanosec(long nanosec) {
        this.nanosec = nanosec;
        settleContents();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy