mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 01:08:50 -06:00
Replace Long by Timestamp
This commit is contained in:
@@ -31,7 +31,7 @@ public class CreateRepetitionCommand extends Command
|
||||
@NonNull
|
||||
final Habit habit;
|
||||
|
||||
final long timestamp;
|
||||
final Timestamp timestamp;
|
||||
|
||||
final int value;
|
||||
|
||||
@@ -42,7 +42,7 @@ public class CreateRepetitionCommand extends Command
|
||||
Repetition newRep;
|
||||
|
||||
public CreateRepetitionCommand(@NonNull Habit habit,
|
||||
long timestamp,
|
||||
Timestamp timestamp,
|
||||
int value)
|
||||
{
|
||||
this.timestamp = timestamp;
|
||||
@@ -108,7 +108,7 @@ public class CreateRepetitionCommand extends Command
|
||||
if(habitId == null) throw new RuntimeException("Habit not saved");
|
||||
|
||||
this.habit = habitId;
|
||||
this.repTimestamp = command.timestamp;
|
||||
this.repTimestamp = command.timestamp.getUnixTime();
|
||||
this.value = command.value;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,8 @@ public class CreateRepetitionCommand extends Command
|
||||
if(h == null) throw new HabitNotFoundException();
|
||||
|
||||
CreateRepetitionCommand command;
|
||||
command = new CreateRepetitionCommand(h, repTimestamp, value);
|
||||
command = new CreateRepetitionCommand(
|
||||
h, new Timestamp(repTimestamp), value);
|
||||
command.setId(id);
|
||||
return command;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class EditHabitCommand extends Command
|
||||
habitList.update(habit);
|
||||
|
||||
if (hasFrequencyChanged || hasTargetChanged)
|
||||
habit.invalidateNewerThan(0);
|
||||
habit.invalidateNewerThan(Timestamp.ZERO);
|
||||
}
|
||||
|
||||
public static class Record
|
||||
|
||||
@@ -31,14 +31,14 @@ public class ToggleRepetitionCommand extends Command
|
||||
@NonNull
|
||||
private HabitList list;
|
||||
|
||||
final long timestamp;
|
||||
final Timestamp timestamp;
|
||||
|
||||
@NonNull
|
||||
final Habit habit;
|
||||
|
||||
public ToggleRepetitionCommand(@NonNull HabitList list,
|
||||
@NonNull Habit habit,
|
||||
long timestamp)
|
||||
Timestamp timestamp)
|
||||
{
|
||||
super();
|
||||
this.list = list;
|
||||
@@ -90,7 +90,7 @@ public class ToggleRepetitionCommand extends Command
|
||||
Long habitId = command.habit.getId();
|
||||
if (habitId == null) throw new RuntimeException("Habit not saved");
|
||||
|
||||
this.repTimestamp = command.timestamp;
|
||||
this.repTimestamp = command.timestamp.getUnixTime();
|
||||
this.habit = habitId;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,8 @@ public class ToggleRepetitionCommand extends Command
|
||||
if (h == null) throw new HabitNotFoundException();
|
||||
|
||||
ToggleRepetitionCommand command;
|
||||
command = new ToggleRepetitionCommand(habitList, h, repTimestamp);
|
||||
command = new ToggleRepetitionCommand(
|
||||
habitList, h, new Timestamp(repTimestamp));
|
||||
command.setId(id);
|
||||
return command;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public class HabitBullCSVImporter extends AbstractImporter
|
||||
Calendar date = DateUtils.getStartOfTodayCalendar();
|
||||
date.set(year, month - 1, day);
|
||||
|
||||
long timestamp = date.getTimeInMillis();
|
||||
Timestamp timestamp = new Timestamp(date.getTimeInMillis());
|
||||
|
||||
int value = Integer.parseInt(line[4]);
|
||||
if (value != 1) continue;
|
||||
|
||||
@@ -173,9 +173,9 @@ public class HabitsCSVExporter
|
||||
writeMultipleHabitsHeader(scoresWriter);
|
||||
writeMultipleHabitsHeader(checksWriter);
|
||||
|
||||
long[] timeframe = getTimeframe();
|
||||
long oldest = timeframe[0];
|
||||
long newest = DateUtils.getStartOfToday();
|
||||
Timestamp[] timeframe = getTimeframe();
|
||||
Timestamp oldest = timeframe[0];
|
||||
Timestamp newest = DateUtils.getToday();
|
||||
|
||||
List<int[]> checkmarks = new ArrayList<>();
|
||||
List<double[]> scores = new ArrayList<>();
|
||||
@@ -185,11 +185,11 @@ public class HabitsCSVExporter
|
||||
scores.add(h.getScores().getValues(oldest, newest));
|
||||
}
|
||||
|
||||
int days = DateUtils.getDaysBetween(oldest, newest);
|
||||
int days = oldest.daysUntil(newest);
|
||||
SimpleDateFormat dateFormat = DateFormats.getCSVDateFormat();
|
||||
for (int i = 0; i <= days; i++)
|
||||
{
|
||||
Date day = new Date(newest - i * DateUtils.millisecondsInOneDay);
|
||||
Date day = newest.minus(i).toJavaDate();
|
||||
|
||||
String date = dateFormat.format(day);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -238,20 +238,20 @@ public class HabitsCSVExporter
|
||||
*
|
||||
* @return the timeframe containing the oldest timestamp and the newest timestamp
|
||||
*/
|
||||
private long[] getTimeframe()
|
||||
private Timestamp[] getTimeframe()
|
||||
{
|
||||
long oldest = Long.MAX_VALUE;
|
||||
long newest = -1;
|
||||
Timestamp oldest = Timestamp.ZERO.plus(1000000);
|
||||
Timestamp newest = Timestamp.ZERO;
|
||||
for (Habit h : selectedHabits)
|
||||
{
|
||||
if(h.getRepetitions().getOldest() == null || h.getRepetitions().getNewest() == null)
|
||||
continue;
|
||||
long currOld = h.getRepetitions().getOldest().getTimestamp();
|
||||
long currNew = h.getRepetitions().getNewest().getTimestamp();
|
||||
oldest = currOld > oldest ? oldest : currOld;
|
||||
newest = currNew < newest ? newest : currNew;
|
||||
Timestamp currOld = h.getRepetitions().getOldest().getTimestamp();
|
||||
Timestamp currNew = h.getRepetitions().getNewest().getTimestamp();
|
||||
oldest = currOld.isOlderThan(oldest) ? oldest : currOld;
|
||||
newest = currNew.isNewerThan(newest) ? newest : currNew;
|
||||
}
|
||||
return new long[]{oldest, newest};
|
||||
return new Timestamp[]{oldest, newest};
|
||||
}
|
||||
|
||||
private String writeZipFile() throws IOException
|
||||
|
||||
@@ -109,7 +109,7 @@ public class LoopDBImporter extends AbstractImporter
|
||||
habitRecord.id.toString());
|
||||
|
||||
for (RepetitionRecord r : reps)
|
||||
h.getRepetitions().toggle(r.timestamp, r.value);
|
||||
h.getRepetitions().toggle(new Timestamp(r.timestamp), r.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ public class RewireDBImporter extends AbstractImporter
|
||||
GregorianCalendar cal = DateUtils.getStartOfTodayCalendar();
|
||||
cal.set(year, month - 1, day);
|
||||
|
||||
habit.getRepetitions().toggle(cal.getTimeInMillis());
|
||||
habit.getRepetitions().toggle(new Timestamp(cal));
|
||||
} while (c.moveToNext());
|
||||
}
|
||||
finally
|
||||
|
||||
@@ -100,7 +100,7 @@ public class TickmateDBImporter extends AbstractImporter
|
||||
GregorianCalendar cal = DateUtils.getStartOfTodayCalendar();
|
||||
cal.set(year, month, day);
|
||||
|
||||
habit.getRepetitions().toggle(cal.getTimeInMillis());
|
||||
habit.getRepetitions().toggle(new Timestamp(cal));
|
||||
} while (c.moveToNext());
|
||||
}
|
||||
finally
|
||||
|
||||
@@ -52,7 +52,7 @@ public final class Checkmark
|
||||
*/
|
||||
public static final int UNCHECKED = 0;
|
||||
|
||||
private final long timestamp;
|
||||
private final Timestamp timestamp;
|
||||
|
||||
/**
|
||||
* The value of the checkmark.
|
||||
@@ -65,17 +65,12 @@ public final class Checkmark
|
||||
*/
|
||||
private final int value;
|
||||
|
||||
public Checkmark(long timestamp, int value)
|
||||
public Checkmark(Timestamp timestamp, int value)
|
||||
{
|
||||
this.timestamp = timestamp;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int compareNewer(Checkmark other)
|
||||
{
|
||||
return Long.signum(this.getTimestamp() - other.getTimestamp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
@@ -91,7 +86,7 @@ public final class Checkmark
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
public long getTimestamp()
|
||||
public Timestamp getTimestamp()
|
||||
{
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@@ -30,10 +30,7 @@ import java.util.*;
|
||||
|
||||
import javax.annotation.concurrent.*;
|
||||
|
||||
import static java.lang.Math.min;
|
||||
import static org.isoron.uhabits.core.models.Checkmark.CHECKED_EXPLICITLY;
|
||||
import static org.isoron.uhabits.core.models.Checkmark.CHECKED_IMPLICITLY;
|
||||
import static org.isoron.uhabits.core.models.Checkmark.UNCHECKED;
|
||||
import static org.isoron.uhabits.core.models.Checkmark.*;
|
||||
|
||||
/**
|
||||
* The collection of {@link Checkmark}s belonging to a habit.
|
||||
@@ -57,32 +54,30 @@ public abstract class CheckmarkList
|
||||
{
|
||||
if (reps.length == 0) throw new IllegalArgumentException();
|
||||
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
long today = DateUtils.getStartOfToday();
|
||||
|
||||
long begin = reps[0].getTimestamp();
|
||||
if (intervals.size() > 0) begin = min(begin, intervals.get(0).begin);
|
||||
|
||||
int nDays = (int) ((today - begin) / day) + 1;
|
||||
Timestamp today = DateUtils.getToday();
|
||||
Timestamp begin = reps[0].getTimestamp();
|
||||
if (intervals.size() > 0) begin = Timestamp.oldest(begin, intervals.get(0).begin);
|
||||
|
||||
int nDays = begin.daysUntil(today) + 1;
|
||||
List<Checkmark> checkmarks = new ArrayList<>(nDays);
|
||||
for (int i = 0; i < nDays; i++)
|
||||
checkmarks.add(new Checkmark(today - day * i, UNCHECKED));
|
||||
checkmarks.add(new Checkmark(today.minus(i), UNCHECKED));
|
||||
|
||||
for (Interval interval : intervals)
|
||||
{
|
||||
for (long date = interval.begin; date <= interval.end; date += day)
|
||||
for (int i = 0; i < interval.length(); i++)
|
||||
{
|
||||
if (date > today) continue;
|
||||
int offset = (int) ((today - date) / day);
|
||||
Timestamp date = interval.begin.plus(i);
|
||||
int offset = date.daysUntil(today);
|
||||
if (offset < 0) continue;
|
||||
checkmarks.set(offset, new Checkmark(date, CHECKED_IMPLICITLY));
|
||||
}
|
||||
}
|
||||
|
||||
for (Repetition rep : reps)
|
||||
{
|
||||
long date = rep.getTimestamp();
|
||||
int offset = (int) ((today - date) / day);
|
||||
Timestamp date = rep.getTimestamp();
|
||||
int offset = date.daysUntil(today);
|
||||
checkmarks.set(offset, new Checkmark(date, CHECKED_EXPLICITLY));
|
||||
}
|
||||
|
||||
@@ -104,7 +99,6 @@ public abstract class CheckmarkList
|
||||
static ArrayList<Interval> buildIntervals(@NonNull Frequency freq,
|
||||
@NonNull Repetition[] reps)
|
||||
{
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
int num = freq.getNumerator();
|
||||
int den = freq.getDenominator();
|
||||
|
||||
@@ -114,12 +108,12 @@ public abstract class CheckmarkList
|
||||
Repetition first = reps[i];
|
||||
Repetition last = reps[i + num - 1];
|
||||
|
||||
long distance = (last.getTimestamp() - first.getTimestamp()) / day;
|
||||
long distance = first.getTimestamp().daysUntil(last.getTimestamp());
|
||||
if (distance >= den) continue;
|
||||
|
||||
long begin = first.getTimestamp();
|
||||
long center = last.getTimestamp();
|
||||
long end = begin + (den - 1) * day;
|
||||
Timestamp begin = first.getTimestamp();
|
||||
Timestamp center = last.getTimestamp();
|
||||
Timestamp end = begin.plus(den - 1);
|
||||
intervals.add(new Interval(begin, center, end));
|
||||
}
|
||||
|
||||
@@ -134,17 +128,15 @@ public abstract class CheckmarkList
|
||||
*/
|
||||
static void snapIntervalsTogether(@NonNull ArrayList<Interval> intervals)
|
||||
{
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
|
||||
for (int i = 1; i < intervals.size(); i++)
|
||||
{
|
||||
Interval curr = intervals.get(i);
|
||||
Interval prev = intervals.get(i - 1);
|
||||
|
||||
long distance = curr.begin - prev.end - day;
|
||||
if (distance <= 0 || curr.end - distance < curr.center) continue;
|
||||
intervals.set(i, new Interval(curr.begin - distance, curr.center,
|
||||
curr.end - distance));
|
||||
int gap = prev.end.daysUntil(curr.begin) - 1;
|
||||
if (gap <= 0 || curr.end.minus(gap).isOlderThan(curr.center)) continue;
|
||||
intervals.set(i, new Interval(curr.begin.minus(gap), curr.center,
|
||||
curr.end.minus(gap)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,8 +168,8 @@ public abstract class CheckmarkList
|
||||
Repetition oldestRep = habit.getRepetitions().getOldest();
|
||||
if (oldestRep == null) return new int[0];
|
||||
|
||||
Long fromTimestamp = oldestRep.getTimestamp();
|
||||
Long toTimestamp = DateUtils.getStartOfToday();
|
||||
Timestamp fromTimestamp = oldestRep.getTimestamp();
|
||||
Timestamp toTimestamp = DateUtils.getToday();
|
||||
|
||||
return getValues(fromTimestamp, toTimestamp);
|
||||
}
|
||||
@@ -195,8 +187,8 @@ public abstract class CheckmarkList
|
||||
* @return the list of checkmarks within the interval.
|
||||
*/
|
||||
@NonNull
|
||||
public abstract List<Checkmark> getByInterval(long fromTimestamp,
|
||||
long toTimestamp);
|
||||
public abstract List<Checkmark> getByInterval(Timestamp fromTimestamp,
|
||||
Timestamp toTimestamp);
|
||||
|
||||
/**
|
||||
* Returns the checkmark for today.
|
||||
@@ -207,7 +199,7 @@ public abstract class CheckmarkList
|
||||
public synchronized final Checkmark getToday()
|
||||
{
|
||||
compute();
|
||||
long today = DateUtils.getStartOfToday();
|
||||
Timestamp today = DateUtils.getToday();
|
||||
return getByInterval(today, today).get(0);
|
||||
}
|
||||
|
||||
@@ -236,9 +228,9 @@ public abstract class CheckmarkList
|
||||
* @param to timestamp for the newest checkmark
|
||||
* @return values for the checkmarks inside the given interval
|
||||
*/
|
||||
public final int[] getValues(long from, long to)
|
||||
public final int[] getValues(Timestamp from, Timestamp to)
|
||||
{
|
||||
if (from > to) return new int[0];
|
||||
if (from.isNewerThan(to)) return new int[0];
|
||||
|
||||
List<Checkmark> checkmarks = getByInterval(from, to);
|
||||
int values[] = new int[checkmarks.size()];
|
||||
@@ -257,7 +249,7 @@ public abstract class CheckmarkList
|
||||
*
|
||||
* @param timestamp the timestamp
|
||||
*/
|
||||
public abstract void invalidateNewerThan(long timestamp);
|
||||
public abstract void invalidateNewerThan(Timestamp timestamp);
|
||||
|
||||
/**
|
||||
* Writes the entire list of checkmarks to the given writer, in CSV format.
|
||||
@@ -275,14 +267,14 @@ public abstract class CheckmarkList
|
||||
values = getAllValues();
|
||||
}
|
||||
|
||||
long timestamp = DateUtils.getStartOfToday();
|
||||
Timestamp timestamp = DateUtils.getToday();
|
||||
SimpleDateFormat dateFormat = DateFormats.getCSVDateFormat();
|
||||
|
||||
for (int value : values)
|
||||
{
|
||||
String date = dateFormat.format(new Date(timestamp));
|
||||
String date = dateFormat.format(timestamp.toJavaDate());
|
||||
out.write(String.format("%s,%d\n", date, value));
|
||||
timestamp -= DateUtils.millisecondsInOneDay;
|
||||
timestamp = timestamp.minus(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,15 +284,15 @@ public abstract class CheckmarkList
|
||||
*/
|
||||
protected final synchronized void compute()
|
||||
{
|
||||
final long today = DateUtils.getStartOfToday();
|
||||
final Timestamp today = DateUtils.getToday();
|
||||
|
||||
Checkmark newest = getNewestComputed();
|
||||
if (newest != null && newest.getTimestamp() == today) return;
|
||||
invalidateNewerThan(0);
|
||||
if (newest != null && newest.getTimestamp().equals(today)) return;
|
||||
invalidateNewerThan(Timestamp.ZERO);
|
||||
|
||||
Repetition oldestRep = habit.getRepetitions().getOldest();
|
||||
if (oldestRep == null) return;
|
||||
final long from = oldestRep.getTimestamp();
|
||||
final Timestamp from = oldestRep.getTimestamp();
|
||||
|
||||
Repetition reps[] = habit
|
||||
.getRepetitions()
|
||||
@@ -331,20 +323,18 @@ public abstract class CheckmarkList
|
||||
{
|
||||
if (reps.length == 0) throw new IllegalArgumentException();
|
||||
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
long today = DateUtils.getStartOfToday();
|
||||
long begin = reps[0].getTimestamp();
|
||||
Timestamp today = DateUtils.getToday();
|
||||
Timestamp begin = reps[0].getTimestamp();
|
||||
|
||||
int nDays = (int) ((today - begin) / day) + 1;
|
||||
int nDays = begin.daysUntil(today) + 1;
|
||||
List<Checkmark> checkmarks = new ArrayList<>(nDays);
|
||||
for (int i = 0; i < nDays; i++)
|
||||
checkmarks.add(new Checkmark(today - day * i, 0));
|
||||
checkmarks.add(new Checkmark(today.minus(i), 0));
|
||||
|
||||
for (Repetition rep : reps)
|
||||
{
|
||||
long date = rep.getTimestamp();
|
||||
int offset = (int) ((today - date) / day);
|
||||
checkmarks.set(offset, new Checkmark(date, rep.getValue()));
|
||||
int offset = rep.getTimestamp().daysUntil(today);
|
||||
checkmarks.set(offset, new Checkmark(rep.getTimestamp(), rep.getValue()));
|
||||
}
|
||||
|
||||
add(checkmarks);
|
||||
@@ -360,19 +350,23 @@ public abstract class CheckmarkList
|
||||
|
||||
static class Interval
|
||||
{
|
||||
final long begin;
|
||||
final Timestamp begin;
|
||||
|
||||
final long center;
|
||||
final Timestamp center;
|
||||
|
||||
final long end;
|
||||
final Timestamp end;
|
||||
|
||||
Interval(long begin, long center, long end)
|
||||
Interval(Timestamp begin, Timestamp center, Timestamp end)
|
||||
{
|
||||
this.begin = begin;
|
||||
this.center = center;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return begin.daysUntil(end) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
|
||||
@@ -303,7 +303,7 @@ public class Habit
|
||||
return data.reminder != null;
|
||||
}
|
||||
|
||||
public void invalidateNewerThan(long timestamp)
|
||||
public void invalidateNewerThan(Timestamp timestamp)
|
||||
{
|
||||
getScores().invalidateNewerThan(timestamp);
|
||||
getCheckmarks().invalidateNewerThan(timestamp);
|
||||
|
||||
@@ -162,9 +162,9 @@ public abstract class HabitList implements Iterable<Habit>
|
||||
{
|
||||
for (Habit h : this)
|
||||
{
|
||||
h.getCheckmarks().invalidateNewerThan(0);
|
||||
h.getStreaks().invalidateNewerThan(0);
|
||||
h.getScores().invalidateNewerThan(0);
|
||||
h.getCheckmarks().invalidateNewerThan(Timestamp.ZERO);
|
||||
h.getStreaks().invalidateNewerThan(Timestamp.ZERO);
|
||||
h.getScores().invalidateNewerThan(Timestamp.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.apache.commons.lang3.builder.*;
|
||||
public final class Repetition
|
||||
{
|
||||
|
||||
private final long timestamp;
|
||||
private final Timestamp timestamp;
|
||||
|
||||
/**
|
||||
* The value of the repetition.
|
||||
@@ -47,7 +47,7 @@ public final class Repetition
|
||||
*
|
||||
* @param timestamp the time this repetition occurred.
|
||||
*/
|
||||
public Repetition(long timestamp, int value)
|
||||
public Repetition(Timestamp timestamp, int value)
|
||||
{
|
||||
this.timestamp = timestamp;
|
||||
this.value = value;
|
||||
@@ -67,7 +67,7 @@ public final class Repetition
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
public long getTimestamp()
|
||||
public Timestamp getTimestamp()
|
||||
{
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public abstract class RepetitionList
|
||||
* @return true if list contains repetition with given timestamp, false
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean containsTimestamp(long timestamp)
|
||||
public boolean containsTimestamp(Timestamp timestamp)
|
||||
{
|
||||
return (getByTimestamp(timestamp) != null);
|
||||
}
|
||||
@@ -77,8 +77,8 @@ public abstract class RepetitionList
|
||||
* @param toTimestamp timestamp of the end of the interval
|
||||
* @return list of repetitions within given time interval
|
||||
*/
|
||||
public abstract List<Repetition> getByInterval(long fromTimestamp,
|
||||
long toTimestamp);
|
||||
public abstract List<Repetition> getByInterval(Timestamp fromTimestamp,
|
||||
Timestamp toTimestamp);
|
||||
|
||||
/**
|
||||
* Returns the repetition that has the given timestamp, or null if none
|
||||
@@ -88,7 +88,7 @@ public abstract class RepetitionList
|
||||
* @return the repetition that has the given timestamp.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract Repetition getByTimestamp(long timestamp);
|
||||
public abstract Repetition getByTimestamp(Timestamp timestamp);
|
||||
|
||||
@NonNull
|
||||
public ModelObservable getObservable()
|
||||
@@ -132,18 +132,19 @@ public abstract class RepetitionList
|
||||
* @return total number of repetitions by month versus day of week
|
||||
*/
|
||||
@NonNull
|
||||
public HashMap<Long, Integer[]> getWeekdayFrequency()
|
||||
public HashMap<Timestamp, Integer[]> getWeekdayFrequency()
|
||||
{
|
||||
List<Repetition> reps = getByInterval(0, DateUtils.getStartOfToday());
|
||||
HashMap<Long, Integer[]> map = new HashMap<>();
|
||||
List<Repetition> reps =
|
||||
getByInterval(Timestamp.ZERO, DateUtils.getToday());
|
||||
HashMap<Timestamp, Integer[]> map = new HashMap<>();
|
||||
|
||||
for (Repetition r : reps)
|
||||
{
|
||||
Calendar date = DateUtils.getCalendar(r.getTimestamp());
|
||||
int weekday = DateUtils.getWeekday(r.getTimestamp());
|
||||
Calendar date = r.getTimestamp().toCalendar();
|
||||
int weekday = r.getTimestamp().getWeekday();
|
||||
date.set(Calendar.DAY_OF_MONTH, 1);
|
||||
|
||||
long timestamp = date.getTimeInMillis();
|
||||
Timestamp timestamp = new Timestamp(date.getTimeInMillis());
|
||||
Integer[] list = map.get(timestamp);
|
||||
|
||||
if (list == null)
|
||||
@@ -184,14 +185,12 @@ public abstract class RepetitionList
|
||||
* @return the repetition that has been added or removed.
|
||||
*/
|
||||
@NonNull
|
||||
public Repetition toggle(long timestamp)
|
||||
public synchronized Repetition toggle(Timestamp timestamp)
|
||||
{
|
||||
if(habit.isNumerical())
|
||||
throw new IllegalStateException("habit must NOT be numerical");
|
||||
|
||||
timestamp = DateUtils.getStartOfDay(timestamp);
|
||||
Repetition rep = getByTimestamp(timestamp);
|
||||
|
||||
if (rep != null) remove(rep);
|
||||
else
|
||||
{
|
||||
@@ -211,7 +210,7 @@ public abstract class RepetitionList
|
||||
@NonNull
|
||||
public abstract long getTotalCount();
|
||||
|
||||
public void toggle(long timestamp, int value)
|
||||
public void toggle(Timestamp timestamp, int value)
|
||||
{
|
||||
Repetition rep = getByTimestamp(timestamp);
|
||||
if(rep != null) remove(rep);
|
||||
|
||||
@@ -32,14 +32,14 @@ public final class Score
|
||||
* Timestamp of the day to which this score applies. Time of day should be
|
||||
* midnight (UTC).
|
||||
*/
|
||||
private final long timestamp;
|
||||
private final Timestamp timestamp;
|
||||
|
||||
/**
|
||||
* Value of the score.
|
||||
*/
|
||||
private final double value;
|
||||
|
||||
public Score(long timestamp, double value)
|
||||
public Score(Timestamp timestamp, double value)
|
||||
{
|
||||
this.timestamp = timestamp;
|
||||
this.value = value;
|
||||
@@ -72,10 +72,10 @@ public final class Score
|
||||
|
||||
public int compareNewer(Score other)
|
||||
{
|
||||
return Long.signum(this.getTimestamp() - other.getTimestamp());
|
||||
return getTimestamp().compare(other.getTimestamp());
|
||||
}
|
||||
|
||||
public long getTimestamp()
|
||||
public Timestamp getTimestamp()
|
||||
{
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
*/
|
||||
public double getTodayValue()
|
||||
{
|
||||
return getValue(DateUtils.getStartOfToday());
|
||||
return getValue(DateUtils.getToday());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,11 +81,11 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
* @param timestamp the timestamp of a day
|
||||
* @return score value for that day
|
||||
*/
|
||||
public final synchronized double getValue(long timestamp)
|
||||
public final synchronized double getValue(Timestamp timestamp)
|
||||
{
|
||||
compute(timestamp, timestamp);
|
||||
Score s = getComputedByTimestamp(timestamp);
|
||||
if(s == null) throw new IllegalStateException();
|
||||
if (s == null) throw new IllegalStateException();
|
||||
return s.getValue();
|
||||
}
|
||||
|
||||
@@ -102,8 +102,8 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
* @return the list of scores within the interval.
|
||||
*/
|
||||
@NonNull
|
||||
public abstract List<Score> getByInterval(long fromTimestamp,
|
||||
long toTimestamp);
|
||||
public abstract List<Score> getByInterval(@NonNull Timestamp fromTimestamp,
|
||||
@NonNull Timestamp toTimestamp);
|
||||
|
||||
/**
|
||||
* Returns the values of the scores that fall inside a certain interval
|
||||
@@ -118,12 +118,12 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
* @param to timestamp for the newest score
|
||||
* @return values for the scores inside the given interval
|
||||
*/
|
||||
public final double[] getValues(long from, long to)
|
||||
public final double[] getValues(Timestamp from, Timestamp to)
|
||||
{
|
||||
List<Score> scores = getByInterval(from, to);
|
||||
double[] values = new double[scores.size()];
|
||||
|
||||
for(int i = 0; i < values.length; i++)
|
||||
for (int i = 0; i < values.length; i++)
|
||||
values[i] = scores.get(i).getValue();
|
||||
|
||||
return values;
|
||||
@@ -132,7 +132,7 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
public List<Score> groupBy(DateUtils.TruncateField field)
|
||||
{
|
||||
computeAll();
|
||||
HashMap<Long, ArrayList<Double>> groups = getGroupedValues(field);
|
||||
HashMap<Timestamp, ArrayList<Double>> groups = getGroupedValues(field);
|
||||
List<Score> scores = groupsToAvgScores(groups);
|
||||
Collections.sort(scores, (s1, s2) -> s2.compareNewer(s1));
|
||||
return scores;
|
||||
@@ -145,7 +145,7 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
*
|
||||
* @param timestamp the oldest timestamp that should be invalidated
|
||||
*/
|
||||
public abstract void invalidateNewerThan(long timestamp);
|
||||
public abstract void invalidateNewerThan(Timestamp timestamp);
|
||||
|
||||
@Override
|
||||
public Iterator<Score> iterator()
|
||||
@@ -171,9 +171,8 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
|
||||
for (Score s : this)
|
||||
{
|
||||
String timestamp = dateFormat.format(s.getTimestamp());
|
||||
String score =
|
||||
String.format("%.4f", s.getValue());
|
||||
String timestamp = dateFormat.format(s.getTimestamp().getUnixTime());
|
||||
String score = String.format("%.4f", s.getValue());
|
||||
out.write(String.format("%s,%s\n", timestamp, score));
|
||||
}
|
||||
}
|
||||
@@ -192,25 +191,24 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
* @param from timestamp of the beginning of the interval
|
||||
* @param to timestamp of the end of the time interval
|
||||
*/
|
||||
protected synchronized void compute(long from, long to)
|
||||
protected synchronized void compute(@NonNull Timestamp from,
|
||||
@NonNull Timestamp to)
|
||||
{
|
||||
final long day = DateUtils.millisecondsInOneDay;
|
||||
|
||||
Score newest = getNewestComputed();
|
||||
Score oldest = getOldestComputed();
|
||||
|
||||
if (newest == null)
|
||||
{
|
||||
Repetition oldestRep = habit.getRepetitions().getOldest();
|
||||
if (oldestRep != null)
|
||||
from = Math.min(from, oldestRep.getTimestamp());
|
||||
if (oldestRep != null) from =
|
||||
Timestamp.oldest(from, oldestRep.getTimestamp());
|
||||
forceRecompute(from, to, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oldest == null) throw new IllegalStateException();
|
||||
forceRecompute(from, oldest.getTimestamp() - day, 0);
|
||||
forceRecompute(newest.getTimestamp() + day, to,
|
||||
forceRecompute(from, oldest.getTimestamp().minus(1), 0);
|
||||
forceRecompute(newest.getTimestamp().plus(1), to,
|
||||
newest.getValue());
|
||||
}
|
||||
}
|
||||
@@ -224,7 +222,7 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
Repetition oldestRep = habit.getRepetitions().getOldest();
|
||||
if (oldestRep == null) return;
|
||||
|
||||
long today = DateUtils.getStartOfToday();
|
||||
Timestamp today = DateUtils.getToday();
|
||||
compute(oldestRep.getTimestamp(), today);
|
||||
}
|
||||
|
||||
@@ -236,7 +234,7 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
* @return the score with given timestamp, or null not yet computed.
|
||||
*/
|
||||
@Nullable
|
||||
protected abstract Score getComputedByTimestamp(long timestamp);
|
||||
protected abstract Score getComputedByTimestamp(Timestamp timestamp);
|
||||
|
||||
/**
|
||||
* Returns the most recent score that has already been computed. If no score
|
||||
@@ -263,11 +261,11 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
* @param previousValue value of the score on the day immediately before the
|
||||
* interval begins
|
||||
*/
|
||||
private void forceRecompute(long from, long to, double previousValue)
|
||||
private void forceRecompute(@NonNull Timestamp from,
|
||||
@NonNull Timestamp to,
|
||||
double previousValue)
|
||||
{
|
||||
if(from > to) return;
|
||||
|
||||
final long day = DateUtils.millisecondsInOneDay;
|
||||
if (from.isNewerThan(to)) return;
|
||||
|
||||
final double freq = habit.getFrequency().toDouble();
|
||||
final int checkmarkValues[] = habit.getCheckmarks().getValues(from, to);
|
||||
@@ -278,31 +276,31 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
{
|
||||
double value = checkmarkValues[checkmarkValues.length - i - 1];
|
||||
|
||||
if(habit.isNumerical())
|
||||
if (habit.isNumerical())
|
||||
{
|
||||
value /= 1000;
|
||||
value /= habit.getTargetValue();
|
||||
value = Math.min(1, value);
|
||||
}
|
||||
|
||||
if(!habit.isNumerical() && value > 0)
|
||||
value = 1;
|
||||
if (!habit.isNumerical() && value > 0) value = 1;
|
||||
|
||||
previousValue = Score.compute(freq, previousValue, value);
|
||||
scores.add(new Score(from + day * i, previousValue));
|
||||
scores.add(new Score(from.plus(i), previousValue));
|
||||
}
|
||||
|
||||
add(scores);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private HashMap<Long, ArrayList<Double>> getGroupedValues(DateUtils.TruncateField field)
|
||||
private HashMap<Timestamp, ArrayList<Double>> getGroupedValues(DateUtils.TruncateField field)
|
||||
{
|
||||
HashMap<Long, ArrayList<Double>> groups = new HashMap<>();
|
||||
HashMap<Timestamp, ArrayList<Double>> groups = new HashMap<>();
|
||||
|
||||
for (Score s : this)
|
||||
{
|
||||
long groupTimestamp = DateUtils.truncate(field, s.getTimestamp());
|
||||
Timestamp groupTimestamp = new Timestamp(
|
||||
DateUtils.truncate(field, s.getTimestamp().getUnixTime()));
|
||||
|
||||
if (!groups.containsKey(groupTimestamp))
|
||||
groups.put(groupTimestamp, new ArrayList<>());
|
||||
@@ -314,11 +312,11 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<Score> groupsToAvgScores(HashMap<Long, ArrayList<Double>> groups)
|
||||
private List<Score> groupsToAvgScores(HashMap<Timestamp, ArrayList<Double>> groups)
|
||||
{
|
||||
List<Score> scores = new LinkedList<>();
|
||||
|
||||
for (Long timestamp : groups.keySet())
|
||||
for (Timestamp timestamp : groups.keySet())
|
||||
{
|
||||
double meanValue = 0.0;
|
||||
ArrayList<Double> groupValues = groups.get(timestamp);
|
||||
|
||||
@@ -20,15 +20,14 @@
|
||||
package org.isoron.uhabits.core.models;
|
||||
|
||||
import org.apache.commons.lang3.builder.*;
|
||||
import org.isoron.uhabits.core.utils.*;
|
||||
|
||||
public final class Streak
|
||||
{
|
||||
private final long start;
|
||||
private final Timestamp start;
|
||||
|
||||
private final long end;
|
||||
private final Timestamp end;
|
||||
|
||||
public Streak(long start, long end)
|
||||
public Streak(Timestamp start, Timestamp end)
|
||||
{
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
@@ -39,25 +38,25 @@ public final class Streak
|
||||
if (this.getLength() != other.getLength())
|
||||
return Long.signum(this.getLength() - other.getLength());
|
||||
|
||||
return Long.signum(this.getEnd() - other.getEnd());
|
||||
return compareNewer(other);
|
||||
}
|
||||
|
||||
public int compareNewer(Streak other)
|
||||
{
|
||||
return Long.signum(this.getEnd() - other.getEnd());
|
||||
return end.compare(other.end);
|
||||
}
|
||||
|
||||
public long getEnd()
|
||||
public Timestamp getEnd()
|
||||
{
|
||||
return end;
|
||||
}
|
||||
|
||||
public long getLength()
|
||||
public int getLength()
|
||||
{
|
||||
return (end - start) / DateUtils.millisecondsInOneDay + 1;
|
||||
return start.daysUntil(end) + 1;
|
||||
}
|
||||
|
||||
public long getStart()
|
||||
public Timestamp getStart()
|
||||
{
|
||||
return start;
|
||||
}
|
||||
|
||||
@@ -63,14 +63,13 @@ public abstract class StreakList
|
||||
return observable;
|
||||
}
|
||||
|
||||
public abstract void invalidateNewerThan(long timestamp);
|
||||
public abstract void invalidateNewerThan(Timestamp timestamp);
|
||||
|
||||
public synchronized void rebuild()
|
||||
{
|
||||
long today = DateUtils.getStartOfToday();
|
||||
|
||||
Long beginning = findBeginning();
|
||||
if (beginning == null || beginning > today) return;
|
||||
Timestamp today = DateUtils.getToday();
|
||||
Timestamp beginning = findBeginning();
|
||||
if (beginning == null || beginning.isNewerThan(today)) return;
|
||||
|
||||
int checks[] = habit.getCheckmarks().getValues(beginning, today);
|
||||
List<Streak> streaks = checkmarksToStreaks(beginning, checks);
|
||||
@@ -88,15 +87,15 @@ public abstract class StreakList
|
||||
* @return the list of streaks.
|
||||
*/
|
||||
@NonNull
|
||||
protected List<Streak> checkmarksToStreaks(long beginning, int[] checks)
|
||||
protected List<Streak> checkmarksToStreaks(Timestamp beginning, int[] checks)
|
||||
{
|
||||
ArrayList<Long> transitions = getTransitions(beginning, checks);
|
||||
ArrayList<Timestamp> transitions = getTransitions(beginning, checks);
|
||||
|
||||
List<Streak> streaks = new LinkedList<>();
|
||||
for (int i = 0; i < transitions.size(); i += 2)
|
||||
{
|
||||
long start = transitions.get(i);
|
||||
long end = transitions.get(i + 1);
|
||||
Timestamp start = transitions.get(i);
|
||||
Timestamp end = transitions.get(i + 1);
|
||||
streaks.add(new Streak(start, end));
|
||||
}
|
||||
|
||||
@@ -109,14 +108,13 @@ public abstract class StreakList
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
protected Long findBeginning()
|
||||
protected Timestamp findBeginning()
|
||||
{
|
||||
Streak newestStreak = getNewestComputed();
|
||||
if (newestStreak != null) return newestStreak.getStart();
|
||||
|
||||
Repetition oldestRep = habit.getRepetitions().getOldest();
|
||||
if (oldestRep != null) return oldestRep.getTimestamp();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -129,21 +127,19 @@ public abstract class StreakList
|
||||
* @return the list of transitions
|
||||
*/
|
||||
@NonNull
|
||||
protected ArrayList<Long> getTransitions(long beginning, int[] checks)
|
||||
protected ArrayList<Timestamp> getTransitions(Timestamp beginning, int[] checks)
|
||||
{
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
long current = beginning;
|
||||
|
||||
ArrayList<Long> list = new ArrayList<>();
|
||||
ArrayList<Timestamp> list = new ArrayList<>();
|
||||
Timestamp current = beginning;
|
||||
list.add(current);
|
||||
|
||||
for (int i = 1; i < checks.length; i++)
|
||||
{
|
||||
current += day;
|
||||
current = current.plus(1);
|
||||
int j = checks.length - i - 1;
|
||||
|
||||
if ((checks[j + 1] == 0 && checks[j] > 0)) list.add(current);
|
||||
if ((checks[j + 1] > 0 && checks[j] == 0)) list.add(current - day);
|
||||
if ((checks[j + 1] > 0 && checks[j] == 0)) list.add(current.minus(1));
|
||||
}
|
||||
|
||||
if (list.size() % 2 == 1) list.add(current);
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.core.models;
|
||||
|
||||
import org.apache.commons.lang3.builder.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.Calendar.DAY_OF_WEEK;
|
||||
|
||||
public class Timestamp
|
||||
{
|
||||
|
||||
public static final long DAY_LENGTH = 86400000;
|
||||
|
||||
public static final Timestamp ZERO = new Timestamp(0);
|
||||
|
||||
private final long unixTime;
|
||||
|
||||
public Timestamp(long unixTime)
|
||||
{
|
||||
if (unixTime < 0 || unixTime % DAY_LENGTH != 0)
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid unix time: " + unixTime);
|
||||
|
||||
this.unixTime = unixTime;
|
||||
}
|
||||
|
||||
public Timestamp(GregorianCalendar cal)
|
||||
{
|
||||
this(cal.getTimeInMillis());
|
||||
}
|
||||
|
||||
public long getUnixTime()
|
||||
{
|
||||
return unixTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns -1 if this timestamp is older than the given timestamp, 1 if this
|
||||
* timestamp is newer, or zero if they are equal.
|
||||
*/
|
||||
public int compare(Timestamp other)
|
||||
{
|
||||
return Long.signum(this.unixTime - other.unixTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) return true;
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Timestamp timestamp = (Timestamp) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(unixTime, timestamp.unixTime)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return new HashCodeBuilder(17, 37).append(unixTime).toHashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given two timestamps, returns whichever timestamp is the oldest one.
|
||||
*/
|
||||
public static Timestamp oldest(Timestamp first, Timestamp second)
|
||||
{
|
||||
return first.unixTime < second.unixTime ? first : second;
|
||||
}
|
||||
|
||||
public Timestamp minus(int days)
|
||||
{
|
||||
return plus(-days);
|
||||
}
|
||||
|
||||
public Timestamp plus(int days)
|
||||
{
|
||||
return new Timestamp(unixTime + DAY_LENGTH * days);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of days between this timestamp and the given one. If
|
||||
* the other timestamp equals this one, returns zero. If the other timestamp
|
||||
* is older than this one, returns a negative number.
|
||||
*/
|
||||
public int daysUntil(Timestamp other)
|
||||
{
|
||||
return (int) ((other.unixTime - this.unixTime) / DAY_LENGTH);
|
||||
}
|
||||
|
||||
public boolean isNewerThan(Timestamp other)
|
||||
{
|
||||
return compare(other) > 0;
|
||||
}
|
||||
|
||||
public boolean isOlderThan(Timestamp other)
|
||||
{
|
||||
return compare(other) < 0;
|
||||
}
|
||||
|
||||
|
||||
public Date toJavaDate()
|
||||
{
|
||||
return new Date(unixTime);
|
||||
}
|
||||
|
||||
public GregorianCalendar toCalendar()
|
||||
{
|
||||
GregorianCalendar day =
|
||||
new GregorianCalendar(TimeZone.getTimeZone("GMT"));
|
||||
day.setTimeInMillis(unixTime);
|
||||
return day;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return new ToStringBuilder(this)
|
||||
.append("unixTime", unixTime)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public int getWeekday()
|
||||
{
|
||||
return toCalendar().get(DAY_OF_WEEK) % 7;
|
||||
}
|
||||
}
|
||||
@@ -22,12 +22,9 @@ package org.isoron.uhabits.core.models.memory;
|
||||
import android.support.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
import org.isoron.uhabits.core.utils.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.isoron.uhabits.core.utils.DateUtils.*;
|
||||
|
||||
/**
|
||||
* In-memory implementation of {@link CheckmarkList}.
|
||||
*/
|
||||
@@ -45,42 +42,42 @@ public class MemoryCheckmarkList extends CheckmarkList
|
||||
public void add(List<Checkmark> checkmarks)
|
||||
{
|
||||
list.addAll(checkmarks);
|
||||
Collections.sort(list, (c1, c2) -> c2.compareNewer(c1));
|
||||
Collections.sort(list,
|
||||
(c1, c2) -> c2.getTimestamp().compare(c1.getTimestamp()));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<Checkmark> getByInterval(long fromTimestamp, long toTimestamp)
|
||||
public synchronized List<Checkmark> getByInterval(Timestamp from,
|
||||
Timestamp to)
|
||||
{
|
||||
compute();
|
||||
|
||||
long newestTimestamp = Long.MIN_VALUE;
|
||||
long oldestTimestamp = Long.MAX_VALUE;
|
||||
Timestamp newestComputed = new Timestamp(0);
|
||||
Timestamp oldestComputed = new Timestamp(0).plus(1000000);
|
||||
|
||||
Checkmark newest = getNewestComputed();
|
||||
Checkmark oldest = getOldestComputed();
|
||||
if(newest != null) newestTimestamp = newest.getTimestamp();
|
||||
if(oldest != null) oldestTimestamp = oldest.getTimestamp();
|
||||
long days = (newestTimestamp - oldestTimestamp) /
|
||||
DateUtils.millisecondsInOneDay;
|
||||
if(newest != null) newestComputed = newest.getTimestamp();
|
||||
if(oldest != null) oldestComputed = oldest.getTimestamp();
|
||||
|
||||
List<Checkmark> filtered = new ArrayList<>((int) days);
|
||||
for(long time = toTimestamp; time >= fromTimestamp; time -= millisecondsInOneDay)
|
||||
List<Checkmark> filtered = new ArrayList<>(
|
||||
Math.max(0, oldestComputed.daysUntil(newestComputed) + 1));
|
||||
|
||||
for(int i = 0; i <= from.daysUntil(to); i++)
|
||||
{
|
||||
if(time > newestTimestamp || time < oldestTimestamp)
|
||||
filtered.add(new Checkmark(time, Checkmark.UNCHECKED));
|
||||
Timestamp t = to.minus(i);
|
||||
if(t.isNewerThan(newestComputed) || t.isOlderThan(oldestComputed))
|
||||
filtered.add(new Checkmark(t, Checkmark.UNCHECKED));
|
||||
else
|
||||
{
|
||||
int offset = (int) ((newestTimestamp - time) / millisecondsInOneDay);
|
||||
filtered.add(list.get(offset));
|
||||
}
|
||||
filtered.add(list.get(t.daysUntil(newestComputed)));
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateNewerThan(long timestamp)
|
||||
public void invalidateNewerThan(Timestamp timestamp)
|
||||
{
|
||||
list.clear();
|
||||
observable.notifyListeners();
|
||||
|
||||
@@ -46,28 +46,29 @@ public class MemoryRepetitionList extends RepetitionList
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Repetition> getByInterval(long fromTimestamp, long toTimestamp)
|
||||
public List<Repetition> getByInterval(Timestamp fromTimestamp, Timestamp toTimestamp)
|
||||
{
|
||||
ArrayList<Repetition> filtered = new ArrayList<>();
|
||||
|
||||
for (Repetition r : list)
|
||||
{
|
||||
long t = r.getTimestamp();
|
||||
if (t >= fromTimestamp && t <= toTimestamp) filtered.add(r);
|
||||
Timestamp t = r.getTimestamp();
|
||||
if (t.isOlderThan(fromTimestamp) || t.isNewerThan(toTimestamp)) continue;
|
||||
filtered.add(r);
|
||||
}
|
||||
|
||||
Collections.sort(filtered,
|
||||
(r1, r2) -> Long.compare(r1.getTimestamp(), r2.getTimestamp()));
|
||||
(r1, r2) -> r1.getTimestamp().compare(r2.getTimestamp()));
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Repetition getByTimestamp(long timestamp)
|
||||
public Repetition getByTimestamp(Timestamp timestamp)
|
||||
{
|
||||
for (Repetition r : list)
|
||||
if (r.getTimestamp() == timestamp) return r;
|
||||
if (r.getTimestamp().equals(timestamp)) return r;
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -76,15 +77,15 @@ public class MemoryRepetitionList extends RepetitionList
|
||||
@Override
|
||||
public Repetition getOldest()
|
||||
{
|
||||
long oldestTime = Long.MAX_VALUE;
|
||||
Timestamp oldestTimestamp = Timestamp.ZERO.plus(1000000);
|
||||
Repetition oldestRep = null;
|
||||
|
||||
for (Repetition rep : list)
|
||||
{
|
||||
if (rep.getTimestamp() < oldestTime)
|
||||
if (rep.getTimestamp().isOlderThan(oldestTimestamp))
|
||||
{
|
||||
oldestRep = rep;
|
||||
oldestTime = rep.getTimestamp();
|
||||
oldestTimestamp = rep.getTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,15 +96,15 @@ public class MemoryRepetitionList extends RepetitionList
|
||||
@Override
|
||||
public Repetition getNewest()
|
||||
{
|
||||
long newestTime = -1;
|
||||
Timestamp newestTimestamp = Timestamp.ZERO;
|
||||
Repetition newestRep = null;
|
||||
|
||||
for (Repetition rep : list)
|
||||
{
|
||||
if (rep.getTimestamp() > newestTime)
|
||||
if (rep.getTimestamp().isNewerThan(newestTimestamp))
|
||||
{
|
||||
newestRep = rep;
|
||||
newestTime = rep.getTimestamp();
|
||||
newestTimestamp = rep.getTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,37 +40,41 @@ public class MemoryScoreList extends ScoreList
|
||||
{
|
||||
list.addAll(scores);
|
||||
Collections.sort(list,
|
||||
(s1, s2) -> Long.signum(s2.getTimestamp() - s1.getTimestamp()));
|
||||
(s1, s2) -> s2.getTimestamp().compare(s1.getTimestamp()));
|
||||
getObservable().notifyListeners();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<Score> getByInterval(long fromTimestamp, long toTimestamp)
|
||||
public List<Score> getByInterval(@NonNull Timestamp fromTimestamp,
|
||||
@NonNull Timestamp toTimestamp)
|
||||
{
|
||||
compute(fromTimestamp, toTimestamp);
|
||||
|
||||
List<Score> filtered = new LinkedList<>();
|
||||
|
||||
for (Score s : list)
|
||||
if (s.getTimestamp() >= fromTimestamp &&
|
||||
s.getTimestamp() <= toTimestamp) filtered.add(s);
|
||||
{
|
||||
if (s.getTimestamp().isNewerThan(toTimestamp) ||
|
||||
s.getTimestamp().isOlderThan(fromTimestamp)) continue;
|
||||
filtered.add(s);
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Score getComputedByTimestamp(long timestamp)
|
||||
public Score getComputedByTimestamp(Timestamp timestamp)
|
||||
{
|
||||
for (Score s : list)
|
||||
if (s.getTimestamp() == timestamp) return s;
|
||||
if (s.getTimestamp().equals(timestamp)) return s;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateNewerThan(long timestamp)
|
||||
public void invalidateNewerThan(Timestamp timestamp)
|
||||
{
|
||||
list.clear();
|
||||
getObservable().notifyListeners();
|
||||
|
||||
@@ -41,13 +41,14 @@ public class MemoryStreakList extends StreakList
|
||||
Streak newest = null;
|
||||
|
||||
for (Streak s : list)
|
||||
if (newest == null || s.getEnd() > newest.getEnd()) newest = s;
|
||||
if (newest == null || s.getEnd().isNewerThan(newest.getEnd()))
|
||||
newest = s;
|
||||
|
||||
return newest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateNewerThan(long timestamp)
|
||||
public void invalidateNewerThan(Timestamp timestamp)
|
||||
{
|
||||
list.clear();
|
||||
observable.notifyListeners();
|
||||
|
||||
@@ -79,7 +79,7 @@ public class SQLiteRepetitionList extends RepetitionList
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Repetition> getByInterval(long timeFrom, long timeTo)
|
||||
public List<Repetition> getByInterval(Timestamp timeFrom, Timestamp timeTo)
|
||||
{
|
||||
loadRecords();
|
||||
return list.getByInterval(timeFrom, timeTo);
|
||||
@@ -87,7 +87,7 @@ public class SQLiteRepetitionList extends RepetitionList
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Repetition getByTimestamp(long timestamp)
|
||||
public Repetition getByTimestamp(Timestamp timestamp)
|
||||
{
|
||||
loadRecords();
|
||||
return list.getByTimestamp(timestamp);
|
||||
@@ -115,7 +115,7 @@ public class SQLiteRepetitionList extends RepetitionList
|
||||
check(habit.getId());
|
||||
repository.execSQL(
|
||||
"delete from repetitions where habit = ? and timestamp = ?",
|
||||
habit.getId(), repetition.getTimestamp());
|
||||
habit.getId(), repetition.getTimestamp().getUnixTime());
|
||||
observable.notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,12 +46,12 @@ public class RepetitionRecord
|
||||
|
||||
public void copyFrom(Repetition repetition)
|
||||
{
|
||||
timestamp = repetition.getTimestamp();
|
||||
timestamp = repetition.getTimestamp().getUnixTime();
|
||||
value = repetition.getValue();
|
||||
}
|
||||
|
||||
public Repetition toRepetition()
|
||||
{
|
||||
return new Repetition(timestamp, value);
|
||||
return new Repetition(new Timestamp(timestamp), value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,9 +94,11 @@ public class Preferences
|
||||
return storage.getInt("last_hint_number", -1);
|
||||
}
|
||||
|
||||
public long getLastHintTimestamp()
|
||||
public Timestamp getLastHintTimestamp()
|
||||
{
|
||||
return storage.getLong("last_hint_timestamp", -1);
|
||||
long unixTime = storage.getLong("last_hint_timestamp", -1);
|
||||
if (unixTime < 0) return null;
|
||||
else return new Timestamp(unixTime);
|
||||
}
|
||||
|
||||
public long getLastSync()
|
||||
@@ -274,10 +276,10 @@ public class Preferences
|
||||
return shouldReverseCheckmarks;
|
||||
}
|
||||
|
||||
public void updateLastHint(int number, long timestamp)
|
||||
public void updateLastHint(int number, Timestamp timestamp)
|
||||
{
|
||||
storage.putInt("last_hint_number", number);
|
||||
storage.putLong("last_hint_timestamp", timestamp);
|
||||
storage.putLong("last_hint_timestamp", timestamp.getUnixTime());
|
||||
}
|
||||
|
||||
public interface Listener
|
||||
|
||||
@@ -71,7 +71,7 @@ public class ReminderScheduler implements CommandRunner.Listener
|
||||
sys.scheduleShowReminder(reminderTime, habit, timestamp);
|
||||
}
|
||||
|
||||
public void scheduleAll()
|
||||
public synchronized void scheduleAll()
|
||||
{
|
||||
HabitList reminderHabits =
|
||||
habitList.getFiltered(HabitMatcher.WITH_ALARM);
|
||||
@@ -99,7 +99,7 @@ public class ReminderScheduler implements CommandRunner.Listener
|
||||
Long time = calendar.getTimeInMillis();
|
||||
|
||||
if (DateUtils.getLocalTime() > time)
|
||||
time += DateUtils.millisecondsInOneDay;
|
||||
time += DateUtils.DAY_LENGTH;
|
||||
|
||||
return applyTimezone(time);
|
||||
}
|
||||
|
||||
@@ -57,14 +57,13 @@ public class HabitFixtures
|
||||
habit.setFrequency(new Frequency(3, 7));
|
||||
habit.setColor(4);
|
||||
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
long today = DateUtils.getStartOfToday();
|
||||
Timestamp today = DateUtils.getToday();
|
||||
int marks[] = { 0, 1, 3, 5, 7, 8, 9, 10, 12, 14, 15, 17, 19, 20, 26, 27,
|
||||
28, 50, 51, 52, 53, 54, 58, 60, 63, 65, 70, 71, 72, 73, 74, 75, 80,
|
||||
81, 83, 89, 90, 91, 95, 102, 103, 108, 109, 120};
|
||||
|
||||
for (int mark : marks)
|
||||
habit.getRepetitions().toggle(today - mark * day);
|
||||
habit.getRepetitions().toggle(today.minus(mark));
|
||||
|
||||
return habit;
|
||||
}
|
||||
@@ -81,14 +80,13 @@ public class HabitFixtures
|
||||
habit.setColor(1);
|
||||
saveIfSQLite(habit);
|
||||
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
long today = DateUtils.getStartOfToday();
|
||||
Timestamp today = DateUtils.getToday();
|
||||
int times[] = { 0, 1, 3, 5, 7, 8, 9, 10 };
|
||||
int values[] = { 100, 200, 300, 400, 500, 600, 700, 800 };
|
||||
|
||||
for(int i = 0; i < times.length; i++)
|
||||
{
|
||||
long timestamp = today - times[i] * day;
|
||||
Timestamp timestamp = today.minus(times[i]);
|
||||
habit.getRepetitions().add(new Repetition(timestamp, values[i]));
|
||||
}
|
||||
|
||||
@@ -103,11 +101,11 @@ public class HabitFixtures
|
||||
habit.setFrequency(new Frequency(2, 3));
|
||||
saveIfSQLite(habit);
|
||||
|
||||
long timestamp = DateUtils.getStartOfToday();
|
||||
Timestamp timestamp = DateUtils.getToday();
|
||||
for (boolean c : NON_DAILY_HABIT_CHECKS)
|
||||
{
|
||||
if (c) habit.getRepetitions().toggle(timestamp);
|
||||
timestamp -= DateUtils.millisecondsInOneDay;
|
||||
timestamp = timestamp.minus(1);
|
||||
}
|
||||
|
||||
return habit;
|
||||
|
||||
@@ -102,7 +102,7 @@ public class NotificationTray
|
||||
reshowAll();
|
||||
}
|
||||
|
||||
public void show(@NonNull Habit habit, long timestamp, long reminderTime)
|
||||
public void show(@NonNull Habit habit, Timestamp timestamp, long reminderTime)
|
||||
{
|
||||
NotificationData data = new NotificationData(timestamp, reminderTime);
|
||||
active.put(habit, data);
|
||||
@@ -143,17 +143,17 @@ public class NotificationTray
|
||||
|
||||
void showNotification(Habit habit,
|
||||
int notificationId,
|
||||
long timestamp,
|
||||
Timestamp timestamp,
|
||||
long reminderTime);
|
||||
}
|
||||
|
||||
class NotificationData
|
||||
{
|
||||
public final long timestamp;
|
||||
public final Timestamp timestamp;
|
||||
|
||||
public final long reminderTime;
|
||||
|
||||
public NotificationData(long timestamp, long reminderTime)
|
||||
public NotificationData(Timestamp timestamp, long reminderTime)
|
||||
{
|
||||
this.timestamp = timestamp;
|
||||
this.reminderTime = reminderTime;
|
||||
@@ -166,7 +166,7 @@ public class NotificationTray
|
||||
|
||||
private final Habit habit;
|
||||
|
||||
private final long timestamp;
|
||||
private final Timestamp timestamp;
|
||||
|
||||
private final long reminderTime;
|
||||
|
||||
@@ -200,7 +200,7 @@ public class NotificationTray
|
||||
Reminder reminder = habit.getReminder();
|
||||
|
||||
boolean reminderDays[] = reminder.getDays().toArray();
|
||||
int weekday = DateUtils.getWeekday(timestamp);
|
||||
int weekday = timestamp.getWeekday();
|
||||
|
||||
return reminderDays[weekday];
|
||||
}
|
||||
|
||||
@@ -304,9 +304,9 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
newData.copyScoresFrom(data);
|
||||
newData.copyCheckmarksFrom(data);
|
||||
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
long dateTo = DateUtils.getStartOfDay(DateUtils.getLocalTime());
|
||||
long dateFrom = dateTo - (checkmarkCount - 1) * day;
|
||||
Timestamp dateTo = new Timestamp(
|
||||
DateUtils.getStartOfDay(DateUtils.getLocalTime()));
|
||||
Timestamp dateFrom = dateTo.minus(checkmarkCount - 1);
|
||||
|
||||
runner.publishProgress(this, -1);
|
||||
|
||||
@@ -319,8 +319,9 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
if (targetId != null && !targetId.equals(id)) continue;
|
||||
|
||||
newData.scores.put(id, habit.getScores().getTodayValue());
|
||||
newData.checkmarks.put(id,
|
||||
habit.getCheckmarks().getValues(dateFrom, dateTo));
|
||||
newData.checkmarks.put(id, habit
|
||||
.getCheckmarks()
|
||||
.getValues(dateFrom, dateTo));
|
||||
|
||||
runner.publishProgress(this, position);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.support.annotation.*;
|
||||
|
||||
import com.google.auto.factory.*;
|
||||
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
import org.isoron.uhabits.core.preferences.*;
|
||||
import org.isoron.uhabits.core.utils.*;
|
||||
|
||||
@@ -64,7 +65,7 @@ public class HintList
|
||||
int next = prefs.getLastHintNumber() + 1;
|
||||
if (next >= hints.length) return null;
|
||||
|
||||
prefs.updateLastHint(next, DateUtils.getStartOfToday());
|
||||
prefs.updateLastHint(next, DateUtils.getToday());
|
||||
return hints[next];
|
||||
}
|
||||
|
||||
@@ -75,7 +76,8 @@ public class HintList
|
||||
*/
|
||||
public boolean shouldShow()
|
||||
{
|
||||
long lastHintTimestamp = prefs.getLastHintTimestamp();
|
||||
return (DateUtils.getStartOfToday() > lastHintTimestamp);
|
||||
Timestamp today = DateUtils.getToday();
|
||||
Timestamp lastHintTimestamp = prefs.getLastHintTimestamp();
|
||||
return (lastHintTimestamp.isOlderThan(today));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ public class ListHabitsBehavior
|
||||
screen.showHabitScreen(h);
|
||||
}
|
||||
|
||||
public void onEdit(@NonNull Habit habit, long timestamp)
|
||||
public void onEdit(@NonNull Habit habit, Timestamp timestamp)
|
||||
{
|
||||
CheckmarkList checkmarks = habit.getCheckmarks();
|
||||
double oldValue = checkmarks.getValues(timestamp, timestamp)[0];
|
||||
@@ -109,7 +109,7 @@ public class ListHabitsBehavior
|
||||
public void onFirstRun()
|
||||
{
|
||||
prefs.setFirstRun(false);
|
||||
prefs.updateLastHint(-1, DateUtils.getStartOfToday());
|
||||
prefs.updateLastHint(-1, DateUtils.getToday());
|
||||
screen.showIntroScreen();
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public class ListHabitsBehavior
|
||||
if (prefs.isFirstRun()) onFirstRun();
|
||||
}
|
||||
|
||||
public void onToggle(@NonNull Habit habit, long timestamp)
|
||||
public void onToggle(@NonNull Habit habit, Timestamp timestamp)
|
||||
{
|
||||
commandRunner.execute(
|
||||
new ToggleRepetitionCommand(habitList, habit, timestamp),
|
||||
|
||||
@@ -56,7 +56,7 @@ public class ShowHabitBehavior
|
||||
screen.showEditHistoryScreen();
|
||||
}
|
||||
|
||||
public void onToggleCheckmark(long timestamp)
|
||||
public void onToggleCheckmark(Timestamp timestamp)
|
||||
{
|
||||
commandRunner.execute(
|
||||
new ToggleRepetitionCommand(habitList, habit, timestamp), null);
|
||||
|
||||
@@ -46,7 +46,7 @@ public class WidgetBehavior
|
||||
this.notificationTray = notificationTray;
|
||||
}
|
||||
|
||||
public void onAddRepetition(@NonNull Habit habit, long timestamp)
|
||||
public void onAddRepetition(@NonNull Habit habit, Timestamp timestamp)
|
||||
{
|
||||
Repetition rep = habit.getRepetitions().getByTimestamp(timestamp);
|
||||
if (rep != null) return;
|
||||
@@ -54,19 +54,19 @@ public class WidgetBehavior
|
||||
notificationTray.cancel(habit);
|
||||
}
|
||||
|
||||
public void onRemoveRepetition(@NonNull Habit habit, long timestamp)
|
||||
public void onRemoveRepetition(@NonNull Habit habit, Timestamp timestamp)
|
||||
{
|
||||
Repetition rep = habit.getRepetitions().getByTimestamp(timestamp);
|
||||
if (rep == null) return;
|
||||
performToggle(habit, timestamp);
|
||||
}
|
||||
|
||||
public void onToggleRepetition(@NonNull Habit habit, long timestamp)
|
||||
public void onToggleRepetition(@NonNull Habit habit, Timestamp timestamp)
|
||||
{
|
||||
performToggle(habit, timestamp);
|
||||
}
|
||||
|
||||
private void performToggle(@NonNull Habit habit, long timestamp)
|
||||
private void performToggle(@NonNull Habit habit, Timestamp timestamp)
|
||||
{
|
||||
commandRunner.execute(
|
||||
new ToggleRepetitionCommand(habitList, habit, timestamp),
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
|
||||
package org.isoron.uhabits.core.utils;
|
||||
|
||||
import android.support.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.Calendar.*;
|
||||
@@ -32,7 +36,7 @@ public abstract class DateUtils
|
||||
/**
|
||||
* Number of milliseconds in one day.
|
||||
*/
|
||||
public static long millisecondsInOneDay = 24 * 60 * 60 * 1000;
|
||||
public static long DAY_LENGTH = 24 * 60 * 60 * 1000;
|
||||
|
||||
public static long applyTimezone(long localTimestamp)
|
||||
{
|
||||
@@ -49,7 +53,7 @@ public abstract class DateUtils
|
||||
return dayOfWeek + "\n" + dayOfMonth;
|
||||
}
|
||||
|
||||
public static GregorianCalendar getCalendar(long timestamp)
|
||||
private static GregorianCalendar getCalendar(long timestamp)
|
||||
{
|
||||
GregorianCalendar day =
|
||||
new GregorianCalendar(TimeZone.getTimeZone("GMT"));
|
||||
@@ -57,7 +61,7 @@ public abstract class DateUtils
|
||||
return day;
|
||||
}
|
||||
|
||||
public static String[] getDayNames(int format)
|
||||
private static String[] getDayNames(int format)
|
||||
{
|
||||
String[] wdays = new String[7];
|
||||
|
||||
@@ -130,9 +134,15 @@ public abstract class DateUtils
|
||||
return getDayNames(SHORT);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Timestamp getToday()
|
||||
{
|
||||
return new Timestamp(getStartOfToday());
|
||||
}
|
||||
|
||||
public static long getStartOfDay(long timestamp)
|
||||
{
|
||||
return (timestamp / millisecondsInOneDay) * millisecondsInOneDay;
|
||||
return (timestamp / DAY_LENGTH) * DAY_LENGTH;
|
||||
}
|
||||
|
||||
public static long getStartOfToday()
|
||||
@@ -142,7 +152,7 @@ public abstract class DateUtils
|
||||
|
||||
public static long millisecondsUntilTomorrow()
|
||||
{
|
||||
return getStartOfToday() + millisecondsInOneDay - getLocalTime();
|
||||
return getStartOfToday() + DAY_LENGTH - getLocalTime();
|
||||
}
|
||||
|
||||
public static GregorianCalendar getStartOfTodayCalendar()
|
||||
@@ -150,7 +160,7 @@ public abstract class DateUtils
|
||||
return getCalendar(getStartOfToday());
|
||||
}
|
||||
|
||||
public static TimeZone getTimezone()
|
||||
private static TimeZone getTimezone()
|
||||
{
|
||||
if(fixedTimeZone != null) return fixedTimeZone;
|
||||
return TimeZone.getDefault();
|
||||
@@ -161,25 +171,6 @@ public abstract class DateUtils
|
||||
fixedTimeZone = tz;
|
||||
}
|
||||
|
||||
public static int getWeekday(long timestamp)
|
||||
{
|
||||
GregorianCalendar day = getCalendar(timestamp);
|
||||
return javaWeekdayToLoopWeekday(day.get(DAY_OF_WEEK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Throughout the code, it is assumed that the weekdays are numbered from 0
|
||||
* (Saturday) to 6 (Friday). In the Java Calendar they are numbered from 1
|
||||
* (Sunday) to 7 (Saturday). This function converts from Java to our
|
||||
* internal representation.
|
||||
*
|
||||
* @return weekday number in the internal interpretation
|
||||
*/
|
||||
public static int javaWeekdayToLoopWeekday(int number)
|
||||
{
|
||||
return number % 7;
|
||||
}
|
||||
|
||||
public static long removeTimezone(long timestamp)
|
||||
{
|
||||
TimeZone tz = getTimezone();
|
||||
@@ -230,18 +221,4 @@ public abstract class DateUtils
|
||||
{
|
||||
MONTH, WEEK_NUMBER, YEAR, QUARTER
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of days between two timestamps (exclusively).
|
||||
*
|
||||
* @param t1 the first timestamp to use in milliseconds
|
||||
* @param t2 the second timestamp to use in milliseconds
|
||||
* @return the number of days between the two timestamps
|
||||
*/
|
||||
public static int getDaysBetween(long t1, long t2)
|
||||
{
|
||||
Date d1 = new Date(t1);
|
||||
Date d2 = new Date(t2);
|
||||
return (int) (Math.abs((d2.getTime() - d1.getTime()) / millisecondsInOneDay));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class MidnightTimer
|
||||
executor = Executors.newSingleThreadScheduledExecutor();
|
||||
executor.scheduleAtFixedRate(() -> notifyListeners(),
|
||||
DateUtils.millisecondsUntilTomorrow() + 1000,
|
||||
DateUtils.millisecondsInOneDay, TimeUnit.MILLISECONDS);
|
||||
DateUtils.DAY_LENGTH, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public synchronized void removeListener(MidnightListener listener)
|
||||
|
||||
@@ -96,7 +96,7 @@ public class CommandParserTest extends BaseUnitTest
|
||||
public void testDecodeCreateRepCommand() throws JSONException
|
||||
{
|
||||
CreateRepetitionCommand original, decoded;
|
||||
original = new CreateRepetitionCommand(habit, 1000, 5);
|
||||
original = new CreateRepetitionCommand(habit, Timestamp.ZERO.plus(100), 5);
|
||||
decoded = (CreateRepetitionCommand) parser.parse(original.toJson());
|
||||
|
||||
MatcherAssert.assertThat(decoded.getId(), equalTo(original.getId()));
|
||||
@@ -140,7 +140,8 @@ public class CommandParserTest extends BaseUnitTest
|
||||
public void testDecodeToggleCommand() throws JSONException
|
||||
{
|
||||
ToggleRepetitionCommand original, decoded;
|
||||
original = new ToggleRepetitionCommand(habitList, habit, 1000);
|
||||
original = new ToggleRepetitionCommand(habitList, habit,
|
||||
Timestamp.ZERO.plus(100));
|
||||
decoded = (ToggleRepetitionCommand) parser.parse(original.toJson());
|
||||
|
||||
MatcherAssert.assertThat(decoded.getId(), equalTo(original.getId()));
|
||||
|
||||
@@ -35,7 +35,7 @@ public class CreateRepetitionCommandTest extends BaseUnitTest
|
||||
|
||||
private Habit habit;
|
||||
|
||||
private long today;
|
||||
private Timestamp today;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
@@ -46,7 +46,7 @@ public class CreateRepetitionCommandTest extends BaseUnitTest
|
||||
habit = fixtures.createShortHabit();
|
||||
habitList.add(habit);
|
||||
|
||||
today = DateUtils.getStartOfToday();
|
||||
today = DateUtils.getToday();
|
||||
command = new CreateRepetitionCommand(habit, today, 100);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ public class ToggleRepetitionCommandTest extends BaseUnitTest
|
||||
|
||||
private ToggleRepetitionCommand command;
|
||||
private Habit habit;
|
||||
private long today;
|
||||
private Timestamp today;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
@@ -44,7 +44,7 @@ public class ToggleRepetitionCommandTest extends BaseUnitTest
|
||||
habit = fixtures.createShortHabit();
|
||||
habitList.add(habit);
|
||||
|
||||
today = DateUtils.getStartOfToday();
|
||||
today = DateUtils.getToday();
|
||||
command = new ToggleRepetitionCommand(habitList, habit, today);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ public class ImportTest extends BaseUnitTest
|
||||
{
|
||||
GregorianCalendar date = DateUtils.getStartOfTodayCalendar();
|
||||
date.set(year, month - 1, day);
|
||||
return h.getRepetitions().containsTimestamp(date.getTimeInMillis());
|
||||
return h.getRepetitions().containsTimestamp(new Timestamp(date));
|
||||
}
|
||||
|
||||
private void importFromFile(String assetFilename) throws IOException
|
||||
|
||||
@@ -28,9 +28,7 @@ import java.util.*;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.core.IsEqual.*;
|
||||
import static org.isoron.uhabits.core.models.Checkmark.CHECKED_EXPLICITLY;
|
||||
import static org.isoron.uhabits.core.models.Checkmark.CHECKED_IMPLICITLY;
|
||||
import static org.isoron.uhabits.core.models.Checkmark.UNCHECKED;
|
||||
import static org.isoron.uhabits.core.models.Checkmark.*;
|
||||
|
||||
public class CheckmarkListTest extends BaseUnitTest
|
||||
{
|
||||
@@ -49,9 +47,6 @@ public class CheckmarkListTest extends BaseUnitTest
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
dayLength = DateUtils.millisecondsInOneDay;
|
||||
today = DateUtils.getStartOfToday();
|
||||
|
||||
nonDailyHabit = fixtures.createShortHabit();
|
||||
habitList.add(nonDailyHabit);
|
||||
|
||||
@@ -281,7 +276,9 @@ public class CheckmarkListTest extends BaseUnitTest
|
||||
@Test
|
||||
public void test_getValues_withInvalidInterval()
|
||||
{
|
||||
int values[] = nonDailyHabit.getCheckmarks().getValues(100L, -100L);
|
||||
int values[] = nonDailyHabit
|
||||
.getCheckmarks()
|
||||
.getValues(new Timestamp(0L).plus(100), new Timestamp(0L));
|
||||
assertThat(values, equalTo(new int[0]));
|
||||
}
|
||||
|
||||
@@ -305,7 +302,9 @@ public class CheckmarkListTest extends BaseUnitTest
|
||||
UNCHECKED
|
||||
};
|
||||
|
||||
int[] actualValues = nonDailyHabit.getCheckmarks().getValues(from, to);
|
||||
int[] actualValues = nonDailyHabit
|
||||
.getCheckmarks()
|
||||
.getValues(new Timestamp(from), new Timestamp(to));
|
||||
|
||||
assertThat(actualValues, equalTo(expectedValues));
|
||||
}
|
||||
@@ -344,15 +343,14 @@ public class CheckmarkListTest extends BaseUnitTest
|
||||
assertThat(writer.toString(), equalTo(expectedCSV));
|
||||
}
|
||||
|
||||
private long day(int offset)
|
||||
private Timestamp day(int offset)
|
||||
{
|
||||
return DateUtils.getStartOfToday() -
|
||||
offset * DateUtils.millisecondsInOneDay;
|
||||
return DateUtils.getToday().minus(offset);
|
||||
}
|
||||
|
||||
private void travelInTime(int days)
|
||||
{
|
||||
DateUtils.setFixedLocalTime(
|
||||
FIXED_LOCAL_TIME + days * DateUtils.millisecondsInOneDay);
|
||||
FIXED_LOCAL_TIME + days * Timestamp.DAY_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class HabitTest extends BaseUnitTest
|
||||
{
|
||||
Habit h = modelFactory.buildHabit();
|
||||
assertFalse(h.isCompletedToday());
|
||||
h.getRepetitions().toggle(getStartOfToday());
|
||||
h.getRepetitions().toggle(getToday());
|
||||
assertTrue(h.isCompletedToday());
|
||||
}
|
||||
|
||||
@@ -100,19 +100,19 @@ public class HabitTest extends BaseUnitTest
|
||||
h.setTargetValue(100.0);
|
||||
assertFalse(h.isCompletedToday());
|
||||
|
||||
h.getRepetitions().toggle(getStartOfToday(), 200);
|
||||
h.getRepetitions().toggle(getToday(), 200);
|
||||
assertTrue(h.isCompletedToday());
|
||||
h.getRepetitions().toggle(getStartOfToday(), 100);
|
||||
h.getRepetitions().toggle(getToday(), 100);
|
||||
assertTrue(h.isCompletedToday());
|
||||
h.getRepetitions().toggle(getStartOfToday(), 50);
|
||||
h.getRepetitions().toggle(getToday(), 50);
|
||||
assertFalse(h.isCompletedToday());
|
||||
|
||||
h.setTargetType(Habit.AT_MOST);
|
||||
h.getRepetitions().toggle(getStartOfToday(), 200);
|
||||
h.getRepetitions().toggle(getToday(), 200);
|
||||
assertFalse(h.isCompletedToday());
|
||||
h.getRepetitions().toggle(getStartOfToday(), 100);
|
||||
h.getRepetitions().toggle(getToday(), 100);
|
||||
assertTrue(h.isCompletedToday());
|
||||
h.getRepetitions().toggle(getStartOfToday(), 50);
|
||||
h.getRepetitions().toggle(getToday(), 50);
|
||||
assertTrue(h.isCompletedToday());
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ import java.util.*;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.hamcrest.core.IsEqual.*;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -43,7 +42,7 @@ public class RepetitionListTest extends BaseUnitTest
|
||||
@NonNull
|
||||
private Habit habit;
|
||||
|
||||
private long today;
|
||||
private Timestamp today;
|
||||
|
||||
private long day;
|
||||
|
||||
@@ -58,14 +57,13 @@ public class RepetitionListTest extends BaseUnitTest
|
||||
habit = fixtures.createEmptyHabit();
|
||||
reps = habit.getRepetitions();
|
||||
|
||||
today = DateUtils.getStartOfToday();
|
||||
day = DateUtils.millisecondsInOneDay;
|
||||
today = DateUtils.getToday();
|
||||
|
||||
reps.toggle(today - 3 * day);
|
||||
reps.toggle(today - 2 * day);
|
||||
reps.toggle(today.minus(3));
|
||||
reps.toggle(today.minus(2));
|
||||
reps.toggle(today);
|
||||
reps.toggle(today - 7 * day);
|
||||
reps.toggle(today - 5 * day);
|
||||
reps.toggle(today.minus(7));
|
||||
reps.toggle(today.minus(5));
|
||||
|
||||
listener = mock(ModelObservable.Listener.class);
|
||||
reps.getObservable().addListener(listener);
|
||||
@@ -82,19 +80,19 @@ public class RepetitionListTest extends BaseUnitTest
|
||||
@Test
|
||||
public void test_contains()
|
||||
{
|
||||
assertThat(reps.containsTimestamp(today), is(true));
|
||||
assertThat(reps.containsTimestamp(today - 2 * day), is(true));
|
||||
assertThat(reps.containsTimestamp(today - 3 * day), is(true));
|
||||
assertTrue(reps.containsTimestamp(today));
|
||||
assertTrue(reps.containsTimestamp(today.minus(2)));
|
||||
assertTrue(reps.containsTimestamp(today.minus(3)));
|
||||
|
||||
assertThat(reps.containsTimestamp(today - day), is(false));
|
||||
assertThat(reps.containsTimestamp(today - 4 * day), is(false));
|
||||
assertFalse(reps.containsTimestamp(today.minus(1)));
|
||||
assertFalse(reps.containsTimestamp(today.minus(4)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_getOldest()
|
||||
{
|
||||
Repetition rep = reps.getOldest();
|
||||
assertThat(rep.getTimestamp(), is(equalTo(today - 7 * day)));
|
||||
assertThat(rep.getTimestamp(), equalTo(today.minus(7)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -134,28 +132,28 @@ public class RepetitionListTest extends BaseUnitTest
|
||||
weekdayCount[month][week]++;
|
||||
monthCount[month]++;
|
||||
}
|
||||
reps.toggle(day.getTimeInMillis());
|
||||
reps.toggle(new Timestamp(day));
|
||||
}
|
||||
}
|
||||
|
||||
day.add(Calendar.DAY_OF_YEAR, 1);
|
||||
}
|
||||
|
||||
HashMap<Long, Integer[]> freq =
|
||||
HashMap<Timestamp, Integer[]> freq =
|
||||
reps.getWeekdayFrequency();
|
||||
|
||||
// Repetitions until November should be counted correctly
|
||||
for (int month = 0; month < 11; month++)
|
||||
{
|
||||
day.set(2015, month, 1);
|
||||
Integer actualCount[] = freq.get(day.getTimeInMillis());
|
||||
Integer actualCount[] = freq.get(new Timestamp(day));
|
||||
if (monthCount[month] == 0) assertThat(actualCount, equalTo(null));
|
||||
else assertThat(actualCount, equalTo(weekdayCount[month]));
|
||||
}
|
||||
|
||||
// Repetitions in December should be discarded
|
||||
day.set(2015, 11, 1);
|
||||
assertThat(freq.get(day.getTimeInMillis()), equalTo(null));
|
||||
assertThat(freq.get(new Timestamp(day)), equalTo(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -167,9 +165,9 @@ public class RepetitionListTest extends BaseUnitTest
|
||||
verify(listener).onModelChange();
|
||||
reset(listener);
|
||||
|
||||
assertFalse(reps.containsTimestamp(today - day));
|
||||
reps.toggle(today - day);
|
||||
assertTrue(reps.containsTimestamp(today - day));
|
||||
assertFalse(reps.containsTimestamp(today.minus(1)));
|
||||
reps.toggle(today.minus(1));
|
||||
assertTrue(reps.containsTimestamp(today.minus(1)));
|
||||
verify(listener).onModelChange();
|
||||
reset(listener);
|
||||
|
||||
|
||||
@@ -117,11 +117,11 @@ public class ScoreListTest extends BaseUnitTest
|
||||
};
|
||||
|
||||
ScoreList scores = habit.getScores();
|
||||
long current = DateUtils.getStartOfToday();
|
||||
Timestamp current = DateUtils.getToday();
|
||||
for (double expectedValue : expectedValues)
|
||||
{
|
||||
assertThat(scores.getValue(current), closeTo(expectedValue, E));
|
||||
current -= DateUtils.millisecondsInOneDay;
|
||||
current = current.minus(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,11 +130,9 @@ public class ScoreListTest extends BaseUnitTest
|
||||
{
|
||||
toggleRepetitions(0, 20);
|
||||
|
||||
long today = DateUtils.getStartOfToday();
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
|
||||
long from = today - 4 * day;
|
||||
long to = today - 2 * day;
|
||||
Timestamp today = DateUtils.getToday();
|
||||
Timestamp from = today.minus(4);
|
||||
Timestamp to = today.minus(2);
|
||||
|
||||
double[] expected = {
|
||||
0.617008, 0.596033, 0.573909,
|
||||
@@ -169,7 +167,7 @@ public class ScoreListTest extends BaseUnitTest
|
||||
assertThat(habit.getScores().getTodayValue(), closeTo(0.101149, E));
|
||||
|
||||
habit.setFrequency(new Frequency(1, 2));
|
||||
habit.getScores().invalidateNewerThan(0);
|
||||
habit.getScores().invalidateNewerThan(new Timestamp(0));
|
||||
|
||||
assertThat(habit.getScores().getTodayValue(), closeTo(0.051922, E));
|
||||
}
|
||||
@@ -194,10 +192,9 @@ public class ScoreListTest extends BaseUnitTest
|
||||
private void toggleRepetitions(final int from, final int to)
|
||||
{
|
||||
RepetitionList reps = habit.getRepetitions();
|
||||
long today = DateUtils.getStartOfToday();
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
Timestamp today = DateUtils.getToday();
|
||||
|
||||
for (int i = from; i < to; i++)
|
||||
reps.toggle(today - i * day);
|
||||
reps.toggle(today.minus(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class StreakListTest extends BaseUnitTest
|
||||
|
||||
private long day;
|
||||
|
||||
private long today;
|
||||
private Timestamp today;
|
||||
|
||||
private ModelObservable.Listener listener;
|
||||
|
||||
@@ -54,25 +54,23 @@ public class StreakListTest extends BaseUnitTest
|
||||
|
||||
listener = mock(ModelObservable.Listener.class);
|
||||
streaks.getObservable().addListener(listener);
|
||||
|
||||
today = DateUtils.getStartOfToday();
|
||||
day = DateUtils.millisecondsInOneDay;
|
||||
today = DateUtils.getToday();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindBeginning_withEmptyHistory()
|
||||
{
|
||||
Habit habit2 = fixtures.createEmptyHabit();
|
||||
Long beginning = habit2.getStreaks().findBeginning();
|
||||
assertThat(beginning, is(nullValue()));
|
||||
Timestamp beginning = habit2.getStreaks().findBeginning();
|
||||
assertNull(beginning);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindBeginning_withLongHistory()
|
||||
{
|
||||
streaks.rebuild();
|
||||
streaks.invalidateNewerThan(0);
|
||||
assertThat(streaks.findBeginning(), equalTo(today - 120 * day));
|
||||
streaks.invalidateNewerThan(new Timestamp(0));
|
||||
assertThat(streaks.findBeginning(), equalTo(today.minus(120)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -82,11 +80,11 @@ public class StreakListTest extends BaseUnitTest
|
||||
|
||||
assertThat(all.size(), equalTo(22));
|
||||
|
||||
assertThat(all.get(3).getEnd(), equalTo(today - 7 * day));
|
||||
assertThat(all.get(3).getStart(), equalTo(today - 10 * day));
|
||||
assertThat(all.get(3).getEnd(), equalTo(today.minus(7)));
|
||||
assertThat(all.get(3).getStart(), equalTo(today.minus(10)));
|
||||
|
||||
assertThat(all.get(17).getEnd(), equalTo(today - 89 * day));
|
||||
assertThat(all.get(17).getStart(), equalTo(today - 91 * day));
|
||||
assertThat(all.get(17).getEnd(), equalTo(today.minus(89)));
|
||||
assertThat(all.get(17).getStart(), equalTo(today.minus(91)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,16 +93,16 @@ public class StreakListTest extends BaseUnitTest
|
||||
List<Streak> best = streaks.getBest(4);
|
||||
assertThat(best.size(), equalTo(4));
|
||||
|
||||
assertThat(best.get(0).getLength(), equalTo(4L));
|
||||
assertThat(best.get(1).getLength(), equalTo(3L));
|
||||
assertThat(best.get(2).getLength(), equalTo(5L));
|
||||
assertThat(best.get(3).getLength(), equalTo(6L));
|
||||
assertThat(best.get(0).getLength(), equalTo(4));
|
||||
assertThat(best.get(1).getLength(), equalTo(3));
|
||||
assertThat(best.get(2).getLength(), equalTo(5));
|
||||
assertThat(best.get(3).getLength(), equalTo(6));
|
||||
|
||||
best = streaks.getBest(2);
|
||||
assertThat(best.size(), equalTo(2));
|
||||
|
||||
assertThat(best.get(0).getLength(), equalTo(5L));
|
||||
assertThat(best.get(1).getLength(), equalTo(6L));
|
||||
assertThat(best.get(0).getLength(), equalTo(5));
|
||||
assertThat(best.get(1).getLength(), equalTo(6));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -113,7 +111,7 @@ public class StreakListTest extends BaseUnitTest
|
||||
Streak s = streaks.getNewestComputed();
|
||||
assertThat(s.getEnd(), equalTo(today));
|
||||
|
||||
streaks.invalidateNewerThan(today - 8 * day);
|
||||
streaks.invalidateNewerThan(today.minus(8));
|
||||
verify(listener).onModelChange();
|
||||
|
||||
s = streaks.getNewestComputed();
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.core.models;
|
||||
|
||||
import org.isoron.uhabits.core.*;
|
||||
import org.isoron.uhabits.core.utils.*;
|
||||
import org.junit.*;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TimestampTest extends BaseUnitTest
|
||||
{
|
||||
@Test
|
||||
public void testCompare() throws Exception
|
||||
{
|
||||
Timestamp t1 = DateUtils.getToday();
|
||||
Timestamp t2 = t1.minus(1);
|
||||
Timestamp t3 = t1.plus(3);
|
||||
|
||||
assertThat(t1.compare(t2), greaterThan(0));
|
||||
assertThat(t1.compare(t1), equalTo(0));
|
||||
assertThat(t1.compare(t3), lessThan(0));
|
||||
|
||||
assertTrue(t1.isNewerThan(t2));
|
||||
assertFalse(t1.isNewerThan(t1));
|
||||
assertFalse(t2.isNewerThan(t1));
|
||||
|
||||
assertTrue(t2.isOlderThan(t1));
|
||||
assertFalse(t1.isOlderThan(t2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDaysUntil() throws Exception
|
||||
{
|
||||
Timestamp t = DateUtils.getToday();
|
||||
assertThat(t.daysUntil(t), equalTo(0));
|
||||
|
||||
assertThat(t.daysUntil(t.plus(1)), equalTo(1));
|
||||
assertThat(t.daysUntil(t.plus(3)), equalTo(3));
|
||||
assertThat(t.daysUntil(t.plus(300)), equalTo(300));
|
||||
|
||||
assertThat(t.daysUntil(t.minus(1)), equalTo(-1));
|
||||
assertThat(t.daysUntil(t.minus(3)), equalTo(-3));
|
||||
assertThat(t.daysUntil(t.minus(300)), equalTo(-300));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -31,17 +31,16 @@ import org.junit.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static junit.framework.TestCase.assertNotNull;
|
||||
import static junit.framework.TestCase.assertNull;
|
||||
import static junit.framework.TestCase.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.core.IsEqual.*;
|
||||
import static org.isoron.uhabits.core.models.Checkmark.CHECKED_EXPLICITLY;
|
||||
import static org.isoron.uhabits.core.models.Checkmark.*;
|
||||
|
||||
public class SQLiteRepetitionListTest extends BaseUnitTest
|
||||
{
|
||||
private Habit habit;
|
||||
|
||||
private long today;
|
||||
private Timestamp today;
|
||||
|
||||
private RepetitionList repetitions;
|
||||
|
||||
@@ -62,20 +61,19 @@ public class SQLiteRepetitionListTest extends BaseUnitTest
|
||||
habit = fixtures.createLongHabit();
|
||||
|
||||
repetitions = habit.getRepetitions();
|
||||
today = DateUtils.getStartOfToday();
|
||||
day = DateUtils.millisecondsInOneDay;
|
||||
today = DateUtils.getToday();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd()
|
||||
{
|
||||
RepetitionRecord record = getByTimestamp(today + day);
|
||||
RepetitionRecord record = getByTimestamp(today.plus(1));
|
||||
assertNull(record);
|
||||
|
||||
Repetition rep = new Repetition(today + day, CHECKED_EXPLICITLY);
|
||||
Repetition rep = new Repetition(today.plus(1), CHECKED_EXPLICITLY);
|
||||
habit.getRepetitions().add(rep);
|
||||
|
||||
record = getByTimestamp(today + day);
|
||||
record = getByTimestamp(today.plus(1));
|
||||
assertNotNull(record);
|
||||
assertThat(record.value, equalTo(CHECKED_EXPLICITLY));
|
||||
}
|
||||
@@ -84,12 +82,12 @@ public class SQLiteRepetitionListTest extends BaseUnitTest
|
||||
public void testGetByInterval()
|
||||
{
|
||||
List<Repetition> reps =
|
||||
repetitions.getByInterval(today - 10 * day, today);
|
||||
repetitions.getByInterval(today.minus(10), today);
|
||||
|
||||
assertThat(reps.size(), equalTo(8));
|
||||
assertThat(reps.get(0).getTimestamp(), equalTo(today - 10 * day));
|
||||
assertThat(reps.get(4).getTimestamp(), equalTo(today - 5 * day));
|
||||
assertThat(reps.get(5).getTimestamp(), equalTo(today - 3 * day));
|
||||
assertThat(reps.get(0).getTimestamp(), equalTo(today.minus(10)));
|
||||
assertThat(reps.get(4).getTimestamp(), equalTo(today.minus(5)));
|
||||
assertThat(reps.get(5).getTimestamp(), equalTo(today.minus(3)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -99,7 +97,7 @@ public class SQLiteRepetitionListTest extends BaseUnitTest
|
||||
assertNotNull(rep);
|
||||
assertThat(rep.getTimestamp(), equalTo(today));
|
||||
|
||||
rep = repetitions.getByTimestamp(today - 2 * day);
|
||||
rep = repetitions.getByTimestamp(today.minus(2));
|
||||
assertNull(rep);
|
||||
}
|
||||
|
||||
@@ -108,7 +106,7 @@ public class SQLiteRepetitionListTest extends BaseUnitTest
|
||||
{
|
||||
Repetition rep = repetitions.getOldest();
|
||||
assertNotNull(rep);
|
||||
assertThat(rep.getTimestamp(), equalTo(today - 120 * day));
|
||||
assertThat(rep.getTimestamp(), equalTo(today.minus(120)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -133,11 +131,11 @@ public class SQLiteRepetitionListTest extends BaseUnitTest
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private RepetitionRecord getByTimestamp(long timestamp)
|
||||
private RepetitionRecord getByTimestamp(Timestamp timestamp)
|
||||
{
|
||||
String query = "where habit = ? and timestamp = ?";
|
||||
String params[] = {
|
||||
Long.toString(habit.getId()), Long.toString(timestamp)
|
||||
Long.toString(habit.getId()), Long.toString(timestamp.getUnixTime())
|
||||
};
|
||||
|
||||
return repository.findFirst(query, params);
|
||||
|
||||
@@ -33,7 +33,7 @@ public class RepetitionRecordTest extends BaseUnitTest
|
||||
@Test
|
||||
public void testRecord() throws Exception
|
||||
{
|
||||
Repetition rep = new Repetition(2000L, 50);
|
||||
Repetition rep = new Repetition(Timestamp.ZERO.plus(100), 50);
|
||||
RepetitionRecord record = new RepetitionRecord();
|
||||
record.copyFrom(rep);
|
||||
assertThat(rep, equalTo(record.toRepetition()));
|
||||
|
||||
@@ -85,7 +85,7 @@ public class HabitCardListCacheTest extends BaseUnitTest
|
||||
public void testCommandListener_single()
|
||||
{
|
||||
Habit h2 = habitList.getByPosition(2);
|
||||
long today = DateUtils.getStartOfToday();
|
||||
Timestamp today = DateUtils.getToday();
|
||||
commandRunner.execute(new ToggleRepetitionCommand(habitList, h2, today),
|
||||
h2.getId());
|
||||
|
||||
@@ -106,12 +106,10 @@ public class HabitCardListCacheTest extends BaseUnitTest
|
||||
assertThat(cache.getHabitByPosition(3), equalTo(h));
|
||||
assertThat(cache.getScore(h.getId()), equalTo(score));
|
||||
|
||||
long today = DateUtils.getStartOfToday();
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
|
||||
Timestamp today = DateUtils.getToday();
|
||||
int[] actualCheckmarks = cache.getCheckmarks(h.getId());
|
||||
int[] expectedCheckmarks =
|
||||
h.getCheckmarks().getValues(today - 9 * day, today);
|
||||
h.getCheckmarks().getValues(today.minus(9), today);
|
||||
|
||||
assertThat(actualCheckmarks, equalTo(expectedCheckmarks));
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package org.isoron.uhabits.core.ui.screens.habits.list;
|
||||
|
||||
import org.isoron.uhabits.core.*;
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
import org.isoron.uhabits.core.preferences.*;
|
||||
import org.isoron.uhabits.core.utils.*;
|
||||
import org.junit.*;
|
||||
@@ -41,16 +42,16 @@ public class HintListTest extends BaseUnitTest
|
||||
@Mock
|
||||
private Preferences prefs;
|
||||
|
||||
private long today;
|
||||
private Timestamp today;
|
||||
|
||||
private long yesterday;
|
||||
private Timestamp yesterday;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
today = DateUtils.getStartOfToday();
|
||||
yesterday = today - DateUtils.millisecondsInOneDay;
|
||||
today = DateUtils.getToday();
|
||||
yesterday = today.minus(1);
|
||||
|
||||
hints = new String[]{ "hint1", "hint2", "hint3" };
|
||||
hintList = new HintList(prefs, hints);
|
||||
|
||||
@@ -83,7 +83,7 @@ public class ListHabitsBehaviorTest extends BaseUnitTest
|
||||
@Test
|
||||
public void testOnEdit()
|
||||
{
|
||||
behavior.onEdit(habit2, DateUtils.getStartOfToday());
|
||||
behavior.onEdit(habit2, DateUtils.getToday());
|
||||
verify(screen).showNumberPicker(eq(0.1), eq("miles"), picker.capture());
|
||||
picker.getValue().onNumberPicked(100);
|
||||
assertThat(habit2.getCheckmarks().getTodayValue(), equalTo(100000));
|
||||
@@ -173,7 +173,7 @@ public class ListHabitsBehaviorTest extends BaseUnitTest
|
||||
public void testOnToggle()
|
||||
{
|
||||
assertTrue(habit1.isCompletedToday());
|
||||
behavior.onToggle(habit1, DateUtils.getStartOfToday());
|
||||
behavior.onToggle(habit1, DateUtils.getToday());
|
||||
assertFalse(habit1.isCompletedToday());
|
||||
}
|
||||
|
||||
|
||||
@@ -134,17 +134,4 @@ public class DateUtilsTest extends BaseUnitTest
|
||||
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_getDaysBetween()
|
||||
{
|
||||
long t1 = timestamp(2016, JANUARY, 1);
|
||||
long t2 = timestamp(2016, JANUARY, 10);
|
||||
long t3 = timestamp(2016, DECEMBER, 31);
|
||||
|
||||
assertThat(DateUtils.getDaysBetween(t1, t1), equalTo(0));
|
||||
assertThat(DateUtils.getDaysBetween(t1, t2), equalTo(9));
|
||||
assertThat(DateUtils.getDaysBetween(t1, t3), equalTo(365));
|
||||
assertThat(DateUtils.getDaysBetween(t3, t1), equalTo(365));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user