Replace Long by Timestamp

pull/316/head^2
Alinson S. Xavier 8 years ago
parent 882ddba324
commit a8aa6f192c

@ -210,9 +210,8 @@ public class BaseAndroidTest extends TestCase
Debug.stopMethodTracing();
}
protected Long day(int offset)
protected Timestamp day(int offset)
{
return DateUtils.getStartOfToday() -
offset * DateUtils.millisecondsInOneDay;
return DateUtils.getToday().minus(offset);
}
}

@ -86,7 +86,7 @@ public class BaseUserInterfaceTest
{
prefs.reset();
prefs.setFirstRun(false);
prefs.updateLastHint(100, DateUtils.getStartOfToday());
prefs.updateLastHint(100, DateUtils.getToday());
habitList.removeAll();
cache.refreshAllHabits();
Thread.sleep(1000);

@ -66,14 +66,13 @@ public class HabitFixtures
habit.setFrequency(new Frequency(3, 7));
habit.setColor(7);
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;
}
@ -89,12 +88,12 @@ public class HabitFixtures
habit.setUnit("steps");
habitList.add(habit);
long timestamp = DateUtils.getStartOfToday();
Timestamp timestamp = DateUtils.getToday();
for (int value : LONG_NUMERICAL_HABIT_CHECKS)
{
Repetition r = new Repetition(timestamp, value);
habit.getRepetitions().add(r);
timestamp -= DateUtils.millisecondsInOneDay;
timestamp = timestamp.minus(1);
}
return habit;
@ -108,11 +107,11 @@ public class HabitFixtures
habit.setFrequency(new Frequency(2, 3));
habitList.add(habit);
long timestamp = DateUtils.getStartOfToday();
Timestamp timestamp = DateUtils.getToday();
for (boolean c : LONG_HABIT_CHECKS)
{
if (c) habit.getRepetitions().toggle(timestamp);
timestamp -= DateUtils.millisecondsInOneDay;
timestamp = timestamp.minus(1);
}
return habit;

@ -44,10 +44,9 @@ public class BarChartTest extends BaseViewTest
super.setUp();
Habit habit = fixtures.createLongNumericalHabit();
view = new BarChart(targetContext);
long today = DateUtils.getStartOfToday();
long day = DateUtils.millisecondsInOneDay;
Timestamp today = DateUtils.getToday();
CheckmarkList checkmarks = habit.getCheckmarks();
view.setCheckmarks(checkmarks.getByInterval(today - 20 * day, today));
view.setCheckmarks(checkmarks.getByInterval(today.minus(20), today));
view.setColor(PaletteUtils.getColor(targetContext, habit.getColor()));
view.setTarget(200.0);
measureView(view, dpToPixels(300), dpToPixels(200));

@ -24,6 +24,7 @@ import android.support.test.runner.*
import org.hamcrest.CoreMatchers.*
import org.hamcrest.MatcherAssert.*
import org.isoron.uhabits.*
import org.isoron.uhabits.core.models.*
import org.isoron.uhabits.core.models.Checkmark.*
import org.isoron.uhabits.utils.*
import org.junit.*
@ -89,7 +90,7 @@ class CheckmarkPanelViewTest : BaseViewTest() {
@Test
fun testToggle() {
var timestamps = mutableListOf<Long>()
var timestamps = mutableListOf<Timestamp>()
view.onToggle = { timestamps.add(it) }
view.buttons[0].performLongClick()
view.buttons[2].performLongClick()
@ -99,12 +100,12 @@ class CheckmarkPanelViewTest : BaseViewTest() {
@Test
fun testToggle_withOffset() {
var timestamps = LongArray(0)
val timestamps = mutableListOf<Timestamp>()
view.dataOffset = 3
view.onToggle = { timestamps += it }
view.buttons[0].performLongClick()
view.buttons[2].performLongClick()
view.buttons[3].performLongClick()
assertThat(timestamps, equalTo(longArrayOf(day(3), day(5), day(6))))
assertThat(timestamps, equalTo(listOf(day(3), day(5), day(6))))
}
}

@ -24,6 +24,7 @@ import android.support.test.runner.*
import org.hamcrest.CoreMatchers.*
import org.hamcrest.MatcherAssert.*
import org.isoron.uhabits.*
import org.isoron.uhabits.core.models.*
import org.isoron.uhabits.utils.*
import org.junit.*
import org.junit.runner.*
@ -84,22 +85,22 @@ class NumberPanelViewTest : BaseViewTest() {
@Test
fun testEdit() {
var timestamps = LongArray(0)
view.onEdit = { timestamps += it }
val timestamps = mutableListOf<Timestamp>()
view.onEdit = { timestamps.plusAssign(it) }
view.buttons[0].performLongClick()
view.buttons[2].performLongClick()
view.buttons[3].performLongClick()
assertThat(timestamps, equalTo(longArrayOf(day(0), day(2), day(3))))
assertThat(timestamps, equalTo(listOf(day(0), day(2), day(3))))
}
@Test
fun testEdit_withOffset() {
var timestamps = LongArray(0)
val timestamps = mutableListOf<Timestamp>()
view.dataOffset = 3
view.onEdit = { timestamps += it }
view.buttons[0].performLongClick()
view.buttons[2].performLongClick()
view.buttons[3].performLongClick()
assertThat(timestamps, equalTo(longArrayOf(day(3), day(5), day(6))))
assertThat(timestamps, equalTo(listOf(day(3), day(5), day(6))))
}
}

@ -28,7 +28,7 @@ import org.junit.*;
import org.junit.runner.*;
@RunWith(AndroidJUnit4.class)
@LargeTest
@MediumTest
public class PerformanceTest extends BaseAndroidTest
{
private Habit habit;

@ -115,14 +115,12 @@ public class BarChart extends ScrollableChart
Random random = new Random();
List<Checkmark> checkmarks = new LinkedList<>();
long timestamp = DateUtils.getStartOfToday();
long day = DateUtils.millisecondsInOneDay;
Timestamp today = DateUtils.getToday();
for (int i = 1; i < 100; i++)
{
int value = random.nextInt(1000);
checkmarks.add(new Checkmark(timestamp, value));
timestamp -= day;
checkmarks.add(new Checkmark(today.minus(i), value));
}
setCheckmarks(checkmarks);
@ -205,7 +203,7 @@ public class BarChart extends ScrollableChart
if (offset >= checkmarks.size()) continue;
double value = checkmarks.get(offset).getValue();
long timestamp = checkmarks.get(offset).getTimestamp();
Timestamp timestamp = checkmarks.get(offset).getTimestamp();
int height = (int) (columnHeight * value / maxValue);
rect.set(0, 0, baseSize, height);
@ -286,13 +284,13 @@ public class BarChart extends ScrollableChart
if (isTransparencyEnabled) pGraph.setXfermode(XFERMODE_SRC);
}
private void drawFooter(Canvas canvas, RectF rect, long currentDate)
private void drawFooter(Canvas canvas, RectF rect, Timestamp currentDate)
{
String yearText = dfYear.format(currentDate);
String monthText = dfMonth.format(currentDate);
String dayText = dfDay.format(currentDate);
String yearText = dfYear.format(currentDate.toJavaDate());
String monthText = dfMonth.format(currentDate.toJavaDate());
String dayText = dfDay.format(currentDate.toJavaDate());
GregorianCalendar calendar = DateUtils.getCalendar(currentDate);
GregorianCalendar calendar = currentDate.toCalendar();
pText.setColor(textColor);
String text;

@ -26,6 +26,7 @@ import android.util.*;
import org.isoron.androidbase.utils.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.utils.*;
import org.isoron.uhabits.utils.*;
@ -67,7 +68,7 @@ public class FrequencyChart extends ScrollableChart
private boolean isBackgroundTransparent;
@NonNull
private HashMap<Long, Integer[]> frequency;
private HashMap<Timestamp, Integer[]> frequency;
private int maxFreq;
public FrequencyChart(Context context)
@ -90,23 +91,21 @@ public class FrequencyChart extends ScrollableChart
postInvalidate();
}
public void setFrequency(HashMap<Long, Integer[]> frequency)
public void setFrequency(HashMap<Timestamp, Integer[]> frequency)
{
this.frequency = frequency;
maxFreq = getMaxFreq(frequency);
postInvalidate();
}
private int getMaxFreq(HashMap<Long, Integer[]> frequency)
private int getMaxFreq(HashMap<Timestamp, Integer[]> frequency)
{
int maxValue = 1;
for (Integer[] values : frequency.values())
{
for (Integer value : values)
{
maxValue = Math.max(value, maxValue);
}
}
return maxValue;
}
@ -194,7 +193,7 @@ public class FrequencyChart extends ScrollableChart
private void drawColumn(Canvas canvas, RectF rect, GregorianCalendar date)
{
Integer values[] = frequency.get(date.getTimeInMillis());
Integer values[] = frequency.get(new Timestamp(date));
float rowHeight = rect.height() / 8.0f;
prevRect.set(rect);
@ -324,7 +323,7 @@ public class FrequencyChart extends ScrollableChart
for (int j = 0; j < 7; j++)
values[j] = rand.nextInt(5);
frequency.put(date.getTimeInMillis(), values);
frequency.put(new Timestamp(date), values);
date.add(Calendar.MONTH, -1);
}
}

@ -28,14 +28,15 @@ import android.view.*;
import org.isoron.androidbase.utils.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.utils.*;
import org.isoron.uhabits.utils.*;
import java.text.*;
import java.util.*;
import static org.isoron.uhabits.core.models.Checkmark.*;
import static org.isoron.androidbase.utils.InterfaceUtils.*;
import static org.isoron.uhabits.core.models.Checkmark.*;
public class HistoryChart extends ScrollableChart
{
@ -135,10 +136,11 @@ public class HistoryChart extends ScrollableChart
return false;
}
final Long timestamp = positionToTimestamp(x, y);
final Timestamp timestamp = positionToTimestamp(x, y);
if (timestamp == null) return false;
int offset = timestampToOffset(timestamp);
Timestamp today = DateUtils.getToday();
int offset = timestamp.daysUntil(today);
if (offset < checkmarks.length)
{
boolean isChecked = checkmarks[offset] == CHECKED_EXPLICITLY;
@ -435,7 +437,8 @@ public class HistoryChart extends ScrollableChart
baseLocation = new RectF();
}
private Long positionToTimestamp(float x, float y)
@Nullable
private Timestamp positionToTimestamp(float x, float y)
{
int col = (int) (x / columnWidth);
int row = (int) (y / columnWidth);
@ -450,15 +453,7 @@ public class HistoryChart extends ScrollableChart
if (DateUtils.getStartOfDay(date.getTimeInMillis()) >
DateUtils.getStartOfToday()) return null;
return date.getTimeInMillis();
}
private int timestampToOffset(Long timestamp)
{
Long day = DateUtils.millisecondsInOneDay;
Long today = DateUtils.getStartOfToday();
return (int) ((today - timestamp) / day);
return new Timestamp(date.getTimeInMillis());
}
private void updateDate()
@ -478,6 +473,6 @@ public class HistoryChart extends ScrollableChart
public interface Controller
{
default void onToggleCheckmark(long timestamp) {}
default void onToggleCheckmark(Timestamp timestamp) {}
}
}

@ -111,17 +111,15 @@ public class ScoreChart extends ScrollableChart
scores = new LinkedList<>();
double previous = 0.5f;
long timestamp = DateUtils.getStartOfToday();
long day = DateUtils.millisecondsInOneDay;
Timestamp timestamp = DateUtils.getToday();
for (int i = 1; i < 100; i++)
{
double step = 0.1f;
double current = previous + random.nextDouble() * step * 2 - step;
current = Math.max(0, Math.min(1.0f, current));
scores.add(new Score(timestamp, current));
scores.add(new Score(timestamp.minus(i), current));
previous = current;
timestamp -= day;
}
}
@ -189,7 +187,7 @@ public class ScoreChart extends ScrollableChart
if (offset >= scores.size()) continue;
double score = scores.get(offset).getValue();
long timestamp = scores.get(offset).getTimestamp();
Timestamp timestamp = scores.get(offset).getTimestamp();
int height = (int) (columnHeight * score);
@ -258,13 +256,13 @@ public class ScoreChart extends ScrollableChart
if (isTransparencyEnabled) initCache(width, height);
}
private void drawFooter(Canvas canvas, RectF rect, long currentDate)
private void drawFooter(Canvas canvas, RectF rect, Timestamp currentDate)
{
String yearText = dfYear.format(currentDate);
String monthText = dfMonth.format(currentDate);
String dayText = dfDay.format(currentDate);
String yearText = dfYear.format(currentDate.toJavaDate());
String monthText = dfMonth.format(currentDate.toJavaDate());
String dayText = dfDay.format(currentDate.toJavaDate());
GregorianCalendar calendar = DateUtils.getCalendar(currentDate);
GregorianCalendar calendar = currentDate.toCalendar();
String text;
int year = calendar.get(Calendar.YEAR);

@ -97,16 +97,15 @@ public class StreakChart extends View
public void populateWithRandomData()
{
long day = DateUtils.millisecondsInOneDay;
long start = DateUtils.getStartOfToday();
Timestamp start = DateUtils.getToday();
LinkedList<Streak> streaks = new LinkedList<>();
for (int i = 0; i < 10; i++)
{
int length = new Random().nextInt(100);
long end = start + length * day;
Timestamp end = start.plus(length);
streaks.add(new Streak(start, end));
start = end + day;
start = end.plus(1);
}
setStreaks(streaks);
@ -215,8 +214,8 @@ public class StreakChart extends View
if (shouldShowLabels)
{
String startLabel = dateFormat.format(new Date(streak.getStart()));
String endLabel = dateFormat.format(new Date(streak.getEnd()));
String startLabel = dateFormat.format(streak.getStart().toJavaDate());
String endLabel = dateFormat.format(streak.getEnd().toJavaDate());
paint.setColor(textColor);
paint.setTextAlign(Paint.Align.RIGHT);
@ -284,9 +283,9 @@ public class StreakChart extends View
minLength = Math.min(minLength, s.getLength());
float lw1 =
paint.measureText(dateFormat.format(new Date(s.getStart())));
paint.measureText(dateFormat.format(s.getStart().toJavaDate()));
float lw2 =
paint.measureText(dateFormat.format(new Date(s.getEnd())));
paint.measureText(dateFormat.format(s.getEnd().toJavaDate()));
maxLabelWidth = Math.max(maxLabelWidth, Math.max(lw1, lw2));
}

@ -22,6 +22,7 @@ package org.isoron.uhabits.activities.habits.list.views
import android.content.*
import com.google.auto.factory.*
import org.isoron.androidbase.activities.*
import org.isoron.uhabits.core.models.*
import org.isoron.uhabits.core.models.Checkmark.*
import org.isoron.uhabits.core.preferences.*
import org.isoron.uhabits.core.utils.*
@ -45,7 +46,7 @@ class CheckmarkPanelView(
setupButtons()
}
var onToggle: (Long) -> Unit = {}
var onToggle: (Timestamp) -> Unit = {}
set(value) {
field = value
setupButtons()
@ -55,11 +56,10 @@ class CheckmarkPanelView(
@Synchronized
override fun setupButtons() {
val today = DateUtils.getStartOfToday()
val day = DateUtils.millisecondsInOneDay
val today = DateUtils.getToday()
buttons.forEachIndexed { index, button ->
val timestamp = today - (index + dataOffset) * day
val timestamp = today.minus(index + dataOffset)
button.value = when {
index + dataOffset < values.size -> values[index + dataOffset]
else -> UNCHECKED

@ -171,10 +171,9 @@ class HabitCardView(
updateBackground(isSelected)
}
fun triggerRipple(timestamp: Long) {
val today = DateUtils.getStartOfToday()
val day = DateUtils.millisecondsInOneDay
val offset = ((today - timestamp) / day).toInt() - dataOffset
fun triggerRipple(timestamp: Timestamp) {
val today = DateUtils.getToday()
val offset = timestamp.daysUntil(today) - dataOffset
val button = checkmarkPanel.buttons[offset]
val y = button.height / 2.0f
val x = checkmarkPanel.x + button.x + (button.width / 2).toFloat()

@ -22,6 +22,7 @@ package org.isoron.uhabits.activities.habits.list.views
import android.content.*
import com.google.auto.factory.*
import org.isoron.androidbase.activities.*
import org.isoron.uhabits.core.models.*
import org.isoron.uhabits.core.preferences.*
import org.isoron.uhabits.core.utils.*
@ -56,7 +57,7 @@ class NumberPanelView(
setupButtons()
}
var onEdit: (Long) -> Unit = {}
var onEdit: (Timestamp) -> Unit = {}
set(value) {
field = value
setupButtons()
@ -66,11 +67,10 @@ class NumberPanelView(
@Synchronized
override fun setupButtons() {
val day = DateUtils.millisecondsInOneDay
val today = DateUtils.getStartOfToday()
val today = DateUtils.getToday()
buttons.forEachIndexed { index, button ->
val timestamp = today - (index + dataOffset) * day
val timestamp = today.minus(index + dataOffset)
button.value = when {
index + dataOffset < values.size -> values[index + dataOffset]
else -> 0.0

@ -73,7 +73,7 @@ public class ShowHabitScreen extends BaseScreen
}
@Override
public void onToggleCheckmark(long timestamp)
public void onToggleCheckmark(Timestamp timestamp)
{
behavior.get().onToggleCheckmark(timestamp);
}

@ -98,9 +98,9 @@ public class BarCard extends HabitCard
@Override
public void doInBackground()
{
long today = DateUtils.getStartOfToday();
Timestamp today = DateUtils.getToday();
List<Checkmark> checkmarks =
habit.getCheckmarks().getByInterval(0, today);
habit.getCheckmarks().getByInterval(Timestamp.ZERO, today);
chart.setCheckmarks(checkmarks);
}

@ -94,7 +94,7 @@ public class FrequencyCard extends HabitCard
public void doInBackground()
{
RepetitionList reps = getHabit().getRepetitions();
HashMap<Long, Integer[]> frequency = reps.getWeekdayFrequency();
HashMap<Timestamp, Integer[]> frequency = reps.getWeekdayFrequency();
chart.setFrequency(frequency);
}

@ -164,9 +164,9 @@ public class OverviewCard extends HabitCard
ScoreList scores = habit.getScores();
long today = DateUtils.getStartOfToday();
long lastMonth = today - 30 * DateUtils.millisecondsInOneDay;
long lastYear = today - 365 * DateUtils.millisecondsInOneDay;
Timestamp today = DateUtils.getToday();
Timestamp lastMonth = today.minus(30);
Timestamp lastYear = today.minus(365);
cache.todayScore = (float) scores.getTodayValue();
cache.lastMonthScore = (float) scores.getValue(lastMonth);

@ -45,7 +45,7 @@ class FireSettingReceiver : BroadcastReceiver() {
.build()
allHabits = app.component.habitList
val args = parseIntent(intent) ?: return
val timestamp = DateUtils.getStartOfToday()
val timestamp = DateUtils.getToday()
val controller = component.widgetController
when (args.action) {

@ -42,16 +42,16 @@ class IntentParser
return habit
}
private fun parseTimestamp(intent: Intent): Long {
val today = DateUtils.getStartOfToday()
private fun parseTimestamp(intent: Intent): Timestamp {
val today = DateUtils.getToday().unixTime
var timestamp = intent.getLongExtra("timestamp", today)
timestamp = DateUtils.getStartOfDay(timestamp)
if (timestamp < 0 || timestamp > today)
throw IllegalArgumentException("timestamp is not valid")
return timestamp
return Timestamp(timestamp)
}
class CheckmarkIntentData(var habit: Habit, var timestamp: Long)
class CheckmarkIntentData(var habit: Habit, var timestamp: Timestamp)
}

@ -35,13 +35,13 @@ class PendingIntentFactory
@AppContext private val context: Context,
private val intentFactory: IntentFactory) {
fun addCheckmark(habit: Habit, timestamp: Long?): PendingIntent =
fun addCheckmark(habit: Habit, timestamp: Timestamp?): PendingIntent =
PendingIntent.getBroadcast(
context, 1,
Intent(context, WidgetReceiver::class.java).apply {
data = Uri.parse(habit.uriString)
action = WidgetReceiver.ACTION_ADD_REPETITION
if (timestamp != null) putExtra("timestamp", timestamp)
if (timestamp != null) putExtra("timestamp", timestamp.unixTime)
},
FLAG_UPDATE_CURRENT)

@ -48,7 +48,7 @@ class AndroidNotificationTray
override fun showNotification(habit: Habit,
notificationId: Int,
timestamp: Long,
timestamp: Timestamp,
reminderTime: Long) {
val checkAction = Action(

@ -128,7 +128,7 @@ public class PebbleReceiver extends PebbleDataReceiver
Habit habit = habitList.getById(habitId);
if (habit == null) return;
long today = DateUtils.getStartOfToday();
Timestamp today = DateUtils.getToday();
commandRunner.execute(
new ToggleRepetitionCommand(habitList, habit, today), habitId);

@ -58,7 +58,7 @@ public class ReminderController
}
public void onShowReminder(@NonNull Habit habit,
long timestamp,
Timestamp timestamp,
long reminderTime)
{
notificationTray.show(habit, timestamp, reminderTime);

@ -79,8 +79,8 @@ public class ReminderReceiver extends BroadcastReceiver
{
case ACTION_SHOW_REMINDER:
if (habit == null) return;
reminderController.onShowReminder(habit, timestamp,
reminderTime);
reminderController.onShowReminder(habit,
new Timestamp(timestamp), reminderTime);
break;
case ACTION_DISMISS_REMINDER:

@ -80,8 +80,8 @@ public class ReminderControllerTest extends BaseAndroidJVMTest
public void testOnShowReminder() throws Exception
{
Habit habit = mock(Habit.class);
controller.onShowReminder(habit, 123, 456);
verify(notificationTray).show(habit, 123, 456);
controller.onShowReminder(habit, Timestamp.ZERO.plus(100), 456);
verify(notificationTray).show(habit, Timestamp.ZERO.plus(100), 456);
verify(reminderScheduler).scheduleAll();
}

@ -40,7 +40,7 @@ public class WidgetControllerTest extends BaseAndroidJVMTest
private Habit habit;
private long today;
private Timestamp today;
private NotificationTray notificationTray;
@ -49,7 +49,7 @@ public class WidgetControllerTest extends BaseAndroidJVMTest
{
super.setUp();
today = DateUtils.getStartOfToday();
today = DateUtils.getToday();
habit = fixtures.createEmptyHabit();
commandRunner = mock(CommandRunner.class);
notificationTray = mock(NotificationTray.class);

@ -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<>(
Math.max(0, oldestComputed.daysUntil(newestComputed) + 1));
List<Checkmark> filtered = new ArrayList<>((int) days);
for(long time = toTimestamp; time >= fromTimestamp; time -= millisecondsInOneDay)
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));
}
}

Loading…
Cancel
Save