From d34fd9341c61d13677e029cb187d4dacff5e44ea Mon Sep 17 00:00:00 2001 From: Normand Briere <nbriere@noware.ca> Date: Fri, 26 Oct 2018 20:31:01 -0400 Subject: [PATCH] Much better AO. --- timeflow/data/time/TimeUnit.java | 472 ++++++++++++++++++++++++++++++---------------------------- 1 files changed, 243 insertions(+), 229 deletions(-) diff --git a/timeflow/data/time/TimeUnit.java b/timeflow/data/time/TimeUnit.java index 760b3be..4032258 100755 --- a/timeflow/data/time/TimeUnit.java +++ b/timeflow/data/time/TimeUnit.java @@ -3,241 +3,255 @@ import java.util.*; import java.text.*; -public class TimeUnit { +public class TimeUnit +{ - public static final TimeUnit YEAR=new TimeUnit("Years", Calendar.YEAR, 365*24*60*60*1000L, "yyyy", "yyyy"); - public static final TimeUnit MONTH=new TimeUnit("Months", Calendar.MONTH, 30*24*60*60*1000L, "MMM", "MMM yyyy"); - public static final TimeUnit WEEK=new TimeUnit("Weeks", Calendar.WEEK_OF_YEAR, 7*24*60*60*1000L, "d", "MMM d yyyy"); - public static final TimeUnit DAY=new TimeUnit("Days", Calendar.DAY_OF_MONTH, 24*60*60*1000L, "d", "MMM d yyyy"); - public static final TimeUnit DAY_OF_WEEK=new TimeUnit("Days", Calendar.DAY_OF_WEEK, 24*60*60*1000L, "d", "MMM d yyyy"); - public static final TimeUnit HOUR=new TimeUnit("Hours", Calendar.HOUR_OF_DAY, 60*60*1000L, "kk:mm", "MMM d yyyy kk:mm"); - public static final TimeUnit MINUTE=new TimeUnit("Minutes", Calendar.MINUTE, 60*1000L, ":mm", "MMM d yyyy kk:mm"); - public static final TimeUnit SECOND=new TimeUnit("Seconds", Calendar.SECOND, 1000L, ":ss", "MMM d yyyy kk:mm:ss"); - public static final TimeUnit DECADE=multipleYears(10); - public static final TimeUnit CENTURY=multipleYears(100); - - private static final double DAY_SIZE=24*60*60*1000L; - - private int quantity; - private long roughSize; - private SimpleDateFormat format, fullFormat; - private String name; - private int calendarCode; - - private TimeUnit() - { - } - - private TimeUnit(String name, int calendarCode, long roughSize, String formatPattern, String fullFormatPattern) - { - this.name=name; - this.calendarCode=calendarCode; - this.roughSize=roughSize; - format=new SimpleDateFormat(formatPattern); - fullFormat=new SimpleDateFormat(fullFormatPattern); - quantity=1; - } - - public String toString() - { - return "[TimeUnit: "+name+"]"; - } + public static final TimeUnit YEAR = new TimeUnit("Years", Calendar.YEAR, 365 * 24 * 60 * 60 * 1000L, "yyyy", "yyyy"); + public static final TimeUnit MONTH = new TimeUnit("Months", Calendar.MONTH, 30 * 24 * 60 * 60 * 1000L, "MMM", "MMM yyyy"); + public static final TimeUnit WEEK = new TimeUnit("Weeks", Calendar.WEEK_OF_YEAR, 7 * 24 * 60 * 60 * 1000L, "d", "MMM d yyyy"); + public static final TimeUnit DAY = new TimeUnit("Days", Calendar.DAY_OF_MONTH, 24 * 60 * 60 * 1000L, "d", "MMM d yyyy"); + public static final TimeUnit DAY_OF_WEEK = new TimeUnit("Days", Calendar.DAY_OF_WEEK, 24 * 60 * 60 * 1000L, "d", "MMM d yyyy"); + public static final TimeUnit HOUR = new TimeUnit("Hours", Calendar.HOUR_OF_DAY, 60 * 60 * 1000L, "kk:mm", "MMM d yyyy kk:mm"); + public static final TimeUnit MINUTE = new TimeUnit("Minutes", Calendar.MINUTE, 60 * 1000L, ":mm", "MMM d yyyy kk:mm"); + public static final TimeUnit SECOND = new TimeUnit("Seconds", Calendar.SECOND, 1000L, ":ss", "MMM d yyyy kk:mm:ss"); + public static final TimeUnit DECADE = multipleYears(10); + public static final TimeUnit CENTURY = multipleYears(100); + private static final double DAY_SIZE = 24 * 60 * 60 * 1000L; + private int quantity; + private long roughSize; + private SimpleDateFormat format, fullFormat; + private String name; + private int calendarCode; - public static TimeUnit multipleYears(int numYears) - { - TimeUnit t=new TimeUnit(); - t.name=numYears+" Years"; - t.calendarCode=Calendar.YEAR; - t.roughSize=YEAR.roughSize*numYears; - t.format=YEAR.format; - t.fullFormat=YEAR.fullFormat; - t.quantity=numYears; - return t; - } - - public static TimeUnit multipleWeeks(int num) - { - TimeUnit t=new TimeUnit(); - t.name=num+" Weeks"; - t.calendarCode=Calendar.WEEK_OF_YEAR; - t.roughSize=WEEK.roughSize*num; - t.format=WEEK.format; - t.fullFormat=WEEK.fullFormat; - t.quantity=num; - return t; - } - - public TimeUnit times(int quantity) - { - TimeUnit t=new TimeUnit(); - t.name=quantity+" "+this.name; - t.calendarCode=this.calendarCode; - t.roughSize=this.roughSize*quantity; - t.format=this.format; - t.fullFormat=this.fullFormat; - t.quantity=quantity; - return t; - - } + private TimeUnit() + { + } - - public int numUnitsIn(TimeUnit u) - { - return (int)Math.round(u.getRoughSize()/(double)getRoughSize()); - } - - public boolean isDayOrLess() - { - return roughSize <= 24*60*60*1000L; - } - - public RoughTime roundDown(long timestamp) - { - return round(timestamp, false); - } - - public RoughTime roundUp(long timestamp) - { - return round(timestamp, true); - } - - private static final int[] calendarUnits={Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY, Calendar.DAY_OF_MONTH, Calendar.MONTH, Calendar.YEAR}; - public RoughTime round(long timestamp, boolean up) - { - Calendar c=TimeUtils.cal(timestamp); - - if (calendarCode==Calendar.WEEK_OF_YEAR ) - { - c.set(Calendar.DAY_OF_WEEK, c.getMinimum(Calendar.DAY_OF_WEEK)); - } - else - { - - // set to minimum all fields of finer granularity. - int roundingCode=calendarCode; - if (calendarCode==Calendar.WEEK_OF_YEAR || calendarCode==Calendar.DAY_OF_WEEK) - roundingCode=Calendar.DAY_OF_MONTH; - for (int i=0; i<calendarUnits.length; i++) - { - if (calendarUnits[i]==roundingCode) - break; - if (i==calendarUnits.length-1) - throw new IllegalArgumentException("Unsupported Calendar Unit: "+calendarCode); - c.set(calendarUnits[i], c.getMinimum(calendarUnits[i])); - } - if (quantity>1) - { - c.set(calendarCode, quantity*(c.get(calendarCode)/quantity)); - } - } - - // if rounding up, then add a unit at current granularity. - if (up) - c.add(calendarCode, quantity); - - return new RoughTime(c.getTimeInMillis(), this); - } - - public int get(long timestamp) - { - Calendar c= TimeUtils.cal(timestamp); - int n=c.get(calendarCode); - return quantity==1 ? n : n%quantity; - } - - public void addTo(RoughTime r) - { - addTo(r,1); - } - - public void addTo(RoughTime r, int times) - { - Calendar c=TimeUtils.cal(r.getTime()); - c.add(calendarCode, quantity*times); - r.setTime(c.getTimeInMillis()); - } - - // Finding the difference between two dates, in a given unit of time, - // is much subtler than you'd think! And annoyingly, the Calendar class does not do - // this for you, even though it actually "knows" how to do so since it - // can add fields. - // - // The most vexing problem is dealing with daylight savings time, - // which means that one day a year has 23 hours and one day has 25 hours. - // We also have to handle the fact that months and years aren't constant lengths. - // - // Rather than write all this ourselves, in this code we - // use the Calendar class to do the heavy lifting. - public long difference(long x, long y) - { - // If this is not one of the hard cases, - // just divide the timespan by the length of time unit. - // Note that we're not worrying about hours and daylight savings time. - if (calendarCode!=Calendar.YEAR && calendarCode!=Calendar.MONTH && - calendarCode!=Calendar.DAY_OF_MONTH && calendarCode!=Calendar.DAY_OF_WEEK && - calendarCode!=Calendar.WEEK_OF_YEAR) - { - return (x-y)/roughSize; - } - - Calendar c1=TimeUtils.cal(x), c2=TimeUtils.cal(y); - int diff=0; - switch (calendarCode) - { - case Calendar.YEAR: - return (c1.get(Calendar.YEAR)-c2.get(Calendar.YEAR))/quantity; - - case Calendar.MONTH: - diff= 12*(c1.get(Calendar.YEAR)-c2.get(Calendar.YEAR))+ - c1.get(Calendar.MONTH)-c2.get(Calendar.MONTH); - return diff/quantity; - - case Calendar.DAY_OF_MONTH: - case Calendar.DAY_OF_WEEK: - case Calendar.DAY_OF_YEAR: - case Calendar.WEEK_OF_MONTH: - case Calendar.WEEK_OF_YEAR: - // This is ugly, but believe me, it beats the alternative methods :-) - // We use the Calendar class's knowledge of daylight savings time. - // and also the fact that if we calculate this naively, then we aren't going - // to be off by more than one in either direction. - int naive=(int)Math.round((x-y)/(double)roughSize); - c2.add(calendarCode, naive*quantity); - if (c1.get(calendarCode)==c2.get(calendarCode)) - return naive/quantity; - c2.add(calendarCode, quantity); - if (c1.get(calendarCode)==c2.get(calendarCode)) - return naive/quantity+1; - return naive/quantity-1; - } - throw new IllegalArgumentException("Unexpected calendar code: "+calendarCode); - } + private TimeUnit(String name, int calendarCode, long roughSize, String formatPattern, String fullFormatPattern) + { + this.name = name; + this.calendarCode = calendarCode; + this.roughSize = roughSize; + format = new SimpleDateFormat(formatPattern); + fullFormat = new SimpleDateFormat(fullFormatPattern); + quantity = 1; + } - public long approxNumInRange(long start, long end) - { - return 1+(end-start)/roughSize; - } - - public long getRoughSize() { - return roughSize; - } + public String toString() + { + return "[TimeUnit: " + name + "]"; + } - public String format(Date date) - { - return format.format(date); - } + public static TimeUnit multipleYears(int numYears) + { + TimeUnit t = new TimeUnit(); + t.name = numYears + " Years"; + t.calendarCode = Calendar.YEAR; + t.roughSize = YEAR.roughSize * numYears; + t.format = YEAR.format; + t.fullFormat = YEAR.fullFormat; + t.quantity = numYears; + return t; + } - public String formatFull(Date date) - { - return fullFormat.format(date); - } + public static TimeUnit multipleWeeks(int num) + { + TimeUnit t = new TimeUnit(); + t.name = num + " Weeks"; + t.calendarCode = Calendar.WEEK_OF_YEAR; + t.roughSize = WEEK.roughSize * num; + t.format = WEEK.format; + t.fullFormat = WEEK.fullFormat; + t.quantity = num; + return t; + } - public String formatFull(long timestamp) - { - return fullFormat.format(new Date(timestamp)); - } + public TimeUnit times(int quantity) + { + TimeUnit t = new TimeUnit(); + t.name = quantity + " " + this.name; + t.calendarCode = this.calendarCode; + t.roughSize = this.roughSize * quantity; + t.format = this.format; + t.fullFormat = this.fullFormat; + t.quantity = quantity; + return t; - public String getName() { - return name; - } + } + + public int numUnitsIn(TimeUnit u) + { + return (int) Math.round(u.getRoughSize() / (double) getRoughSize()); + } + + public boolean isDayOrLess() + { + return roughSize <= 24 * 60 * 60 * 1000L; + } + + public RoughTime roundDown(long timestamp) + { + return round(timestamp, false); + } + + public RoughTime roundUp(long timestamp) + { + return round(timestamp, true); + } + private static final int[] calendarUnits = + { + Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY, Calendar.DAY_OF_MONTH, Calendar.MONTH, Calendar.YEAR + }; + + public RoughTime round(long timestamp, boolean up) + { + Calendar c = TimeUtils.cal(timestamp); + + if (calendarCode == Calendar.WEEK_OF_YEAR) + { + c.set(Calendar.DAY_OF_WEEK, c.getMinimum(Calendar.DAY_OF_WEEK)); + } else + { + + // set to minimum all fields of finer granularity. + int roundingCode = calendarCode; + if (calendarCode == Calendar.WEEK_OF_YEAR || calendarCode == Calendar.DAY_OF_WEEK) + { + roundingCode = Calendar.DAY_OF_MONTH; + } + for (int i = 0; i < calendarUnits.length; i++) + { + if (calendarUnits[i] == roundingCode) + { + break; + } + if (i == calendarUnits.length - 1) + { + throw new IllegalArgumentException("Unsupported Calendar Unit: " + calendarCode); + } + c.set(calendarUnits[i], c.getMinimum(calendarUnits[i])); + } + if (quantity > 1) + { + c.set(calendarCode, quantity * (c.get(calendarCode) / quantity)); + } + } + + // if rounding up, then add a unit at current granularity. + if (up) + { + c.add(calendarCode, quantity); + } + + return new RoughTime(c.getTimeInMillis(), this); + } + + public int get(long timestamp) + { + Calendar c = TimeUtils.cal(timestamp); + int n = c.get(calendarCode); + return quantity == 1 ? n : n % quantity; + } + + public void addTo(RoughTime r) + { + addTo(r, 1); + } + + public void addTo(RoughTime r, int times) + { + Calendar c = TimeUtils.cal(r.getTime()); + c.add(calendarCode, quantity * times); + r.setTime(c.getTimeInMillis()); + } + + // Finding the difference between two dates, in a given unit of time, + // is much subtler than you'd think! And annoyingly, the Calendar class does not do + // this for you, even though it actually "knows" how to do so since it + // can add fields. + // + // The most vexing problem is dealing with daylight savings time, + // which means that one day a year has 23 hours and one day has 25 hours. + // We also have to handle the fact that months and years aren't constant lengths. + // + // Rather than write all this ourselves, in this code we + // use the Calendar class to do the heavy lifting. + public long difference(long x, long y) + { + // If this is not one of the hard cases, + // just divide the timespan by the length of time unit. + // Note that we're not worrying about hours and daylight savings time. + if (calendarCode != Calendar.YEAR && calendarCode != Calendar.MONTH + && calendarCode != Calendar.DAY_OF_MONTH && calendarCode != Calendar.DAY_OF_WEEK + && calendarCode != Calendar.WEEK_OF_YEAR) + { + return (x - y) / roughSize; + } + + Calendar c1 = TimeUtils.cal(x), c2 = TimeUtils.cal(y); + int diff = 0; + switch (calendarCode) + { + case Calendar.YEAR: + return (c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR)) / quantity; + + case Calendar.MONTH: + diff = 12 * (c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR)) + + c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH); + return diff / quantity; + + case Calendar.DAY_OF_MONTH: + case Calendar.DAY_OF_WEEK: + case Calendar.DAY_OF_YEAR: + case Calendar.WEEK_OF_MONTH: + case Calendar.WEEK_OF_YEAR: + // This is ugly, but believe me, it beats the alternative methods :-) + // We use the Calendar class's knowledge of daylight savings time. + // and also the fact that if we calculate this naively, then we aren't going + // to be off by more than one in either direction. + int naive = (int) Math.round((x - y) / (double) roughSize); + c2.add(calendarCode, naive * quantity); + if (c1.get(calendarCode) == c2.get(calendarCode)) + { + return naive / quantity; + } + c2.add(calendarCode, quantity); + if (c1.get(calendarCode) == c2.get(calendarCode)) + { + return naive / quantity + 1; + } + return naive / quantity - 1; + } + throw new IllegalArgumentException("Unexpected calendar code: " + calendarCode); + } + + public long approxNumInRange(long start, long end) + { + return 1 + (end - start) / roughSize; + } + + public long getRoughSize() + { + return roughSize; + } + + public String format(Date date) + { + return format.format(date); + } + + public String formatFull(Date date) + { + return fullFormat.format(date); + } + + public String formatFull(long timestamp) + { + return fullFormat.format(new Date(timestamp)); + } + + public String getName() + { + return name; + } } -- Gitblit v1.6.2