From 15a4a2c002c71dab982300f58ca16ecd2ad429b4 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Sat, 23 Jul 2016 19:19:22 -0400 Subject: [PATCH] Refactor reminders; replace int by WeekdayList --- .../org/isoron/uhabits/espresso/MainTest.java | 2 +- .../org/isoron/uhabits/io/ImportTest.java | 6 +- .../habits/show/views/SubtitleCardTest.java | 3 +- .../java/org/isoron/uhabits/HabitLogger.java | 2 +- .../isoron/uhabits/io/HabitsCSVExporter.java | 2 +- .../isoron/uhabits/io/RewireDBImporter.java | 2 +- .../isoron/uhabits/models/CheckmarkList.java | 2 +- .../org/isoron/uhabits/models/Reminder.java | 16 +-- .../org/isoron/uhabits/models/ScoreList.java | 2 +- .../isoron/uhabits/models/WeekdayList.java | 65 +++++++++ .../models/sqlite/records/HabitRecord.java | 6 +- .../uhabits/receivers/ReminderReceiver.java | 3 +- .../org/isoron/uhabits/ui/BaseSystem.java | 3 +- .../ui/common/views/FrequencyChart.java | 4 +- .../uhabits/ui/common/views/HistoryChart.java | 4 +- .../uhabits/ui/common/views/ScoreChart.java | 6 +- .../uhabits/ui/habits/edit/BaseDialog.java | 12 +- .../ui/habits/edit/BaseDialogHelper.java | 2 +- .../isoron/uhabits/utils/DatabaseUtils.java | 2 +- .../org/isoron/uhabits/utils/DateFormats.java | 62 +++++++++ .../org/isoron/uhabits/utils/DateUtils.java | 123 ++++-------------- .../isoron/uhabits/models/HabitListTest.java | 3 +- .../org/isoron/uhabits/models/HabitTest.java | 7 +- .../isoron/uhabits/models/ScoreListTest.java | 4 +- .../uhabits/models/WeekdayListTest.java | 46 +++++++ .../isoron/uhabits/utils/DateUtilsTest.java | 76 ++++++----- .../uhabits/utils/ReminderSchedulerTest.java | 10 +- 27 files changed, 287 insertions(+), 188 deletions(-) create mode 100644 app/src/main/java/org/isoron/uhabits/models/WeekdayList.java create mode 100644 app/src/main/java/org/isoron/uhabits/utils/DateFormats.java create mode 100644 app/src/test/java/org/isoron/uhabits/models/WeekdayListTest.java diff --git a/app/src/androidTest/java/org/isoron/uhabits/espresso/MainTest.java b/app/src/androidTest/java/org/isoron/uhabits/espresso/MainTest.java index 420f90d36..382d5db4f 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/espresso/MainTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/espresso/MainTest.java @@ -263,7 +263,7 @@ public class MainTest clickMenuItem(R.string.settings); String date = - DateUtils.getBackupDateFormat().format(DateUtils.getLocalTime()); + DateFormats.getBackupDateFormat().format(DateUtils.getLocalTime()); date = date.substring(0, date.length() - 2); clickSettingsItem("Export full backup"); diff --git a/app/src/androidTest/java/org/isoron/uhabits/io/ImportTest.java b/app/src/androidTest/java/org/isoron/uhabits/io/ImportTest.java index 21f2e4a7f..9947be120 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/io/ImportTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/io/ImportTest.java @@ -82,7 +82,8 @@ public class ImportTest extends BaseAndroidTest Habit habit = habitList.getByPosition(0); assertThat(habit.getName(), equalTo("Wake up early")); - assertThat(habit.getFrequency(), equalTo(Frequency.THREE_TIMES_PER_WEEK)); + assertThat(habit.getFrequency(), + equalTo(Frequency.THREE_TIMES_PER_WEEK)); assertTrue(containsRepetition(habit, 2016, 3, 14)); assertTrue(containsRepetition(habit, 2016, 3, 16)); assertFalse(containsRepetition(habit, 2016, 3, 17)); @@ -115,8 +116,7 @@ public class ImportTest extends BaseAndroidTest assertThat(reminder.getHour(), equalTo(8)); assertThat(reminder.getMinute(), equalTo(0)); boolean[] reminderDays = { false, true, true, true, true, true, false }; - assertThat(reminder.getDays(), - equalTo(DateUtils.packWeekdayList(reminderDays))); + assertThat(reminder.getDays().toArray(), equalTo(reminderDays)); } @Test diff --git a/app/src/androidTest/java/org/isoron/uhabits/ui/habits/show/views/SubtitleCardTest.java b/app/src/androidTest/java/org/isoron/uhabits/ui/habits/show/views/SubtitleCardTest.java index f9031ff3c..42b8f3ab1 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/ui/habits/show/views/SubtitleCardTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/ui/habits/show/views/SubtitleCardTest.java @@ -25,7 +25,6 @@ import android.view.*; import org.isoron.uhabits.*; import org.isoron.uhabits.models.*; -import org.isoron.uhabits.utils.*; import org.junit.*; import org.junit.runner.*; @@ -46,7 +45,7 @@ public class SubtitleCardTest extends BaseViewTest super.setUp(); habit = fixtures.createLongHabit(); - habit.setReminder(new Reminder(8, 30, DateUtils.ALL_WEEK_DAYS)); + habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY)); view = (SubtitleCard) LayoutInflater .from(targetContext) diff --git a/app/src/main/java/org/isoron/uhabits/HabitLogger.java b/app/src/main/java/org/isoron/uhabits/HabitLogger.java index 6a0f83e3d..57deafbb0 100644 --- a/app/src/main/java/org/isoron/uhabits/HabitLogger.java +++ b/app/src/main/java/org/isoron/uhabits/HabitLogger.java @@ -45,7 +45,7 @@ public class HabitLogger int min = Math.min(3, habit.getName().length()); String name = habit.getName().substring(0, min); - DateFormat df = DateUtils.getBackupDateFormat(); + DateFormat df = DateFormats.getBackupDateFormat(); String time = df.format(new Date(reminderTime)); Log.i("ReminderHelper", diff --git a/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java b/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java index c308c0bb0..320910f12 100644 --- a/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java @@ -151,7 +151,7 @@ public class HabitsCSVExporter private String writeZipFile() throws IOException { - SimpleDateFormat dateFormat = DateUtils.getCSVDateFormat(); + SimpleDateFormat dateFormat = DateFormats.getCSVDateFormat(); String date = dateFormat.format(DateUtils.getStartOfToday()); String zipFilename = String.format("%s/Loop Habits CSV %s.zip", exportDirName, date); diff --git a/app/src/main/java/org/isoron/uhabits/io/RewireDBImporter.java b/app/src/main/java/org/isoron/uhabits/io/RewireDBImporter.java index 2717f4eb0..e2020f360 100644 --- a/app/src/main/java/org/isoron/uhabits/io/RewireDBImporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/RewireDBImporter.java @@ -203,7 +203,7 @@ public class RewireDBImporter extends AbstractImporter int hour = rewireReminder / 60; int minute = rewireReminder % 60; - Integer days = DateUtils.packWeekdayList(reminderDays); + WeekdayList days = new WeekdayList(reminderDays); Reminder reminder = new Reminder(hour, minute, days); habit.setReminder(reminder); diff --git a/app/src/main/java/org/isoron/uhabits/models/CheckmarkList.java b/app/src/main/java/org/isoron/uhabits/models/CheckmarkList.java index 701bedc64..500aba268 100644 --- a/app/src/main/java/org/isoron/uhabits/models/CheckmarkList.java +++ b/app/src/main/java/org/isoron/uhabits/models/CheckmarkList.java @@ -161,7 +161,7 @@ public abstract class CheckmarkList int values[] = getAllValues(); long timestamp = DateUtils.getStartOfToday(); - SimpleDateFormat dateFormat = DateUtils.getCSVDateFormat(); + SimpleDateFormat dateFormat = DateFormats.getCSVDateFormat(); for (int value : values) { diff --git a/app/src/main/java/org/isoron/uhabits/models/Reminder.java b/app/src/main/java/org/isoron/uhabits/models/Reminder.java index a0af9661b..88d54e293 100644 --- a/app/src/main/java/org/isoron/uhabits/models/Reminder.java +++ b/app/src/main/java/org/isoron/uhabits/models/Reminder.java @@ -19,29 +19,25 @@ package org.isoron.uhabits.models; +import android.support.annotation.*; + public final class Reminder { private final int hour; private final int minute; - private final int days; + private final WeekdayList days; - public Reminder(int hour, int minute, int days) + public Reminder(int hour, int minute, @NonNull WeekdayList days) { this.hour = hour; this.minute = minute; this.days = days; } - /** - * Returns the days of the week the reminder should be shown. - *

- * This field can be converted to a list of booleans using the method - * DateUtils.unpackWeekdayList and converted back to an integer by using the - * method DateUtils.packWeekdayList. - */ - public int getDays() + @NonNull + public WeekdayList getDays() { return days; } diff --git a/app/src/main/java/org/isoron/uhabits/models/ScoreList.java b/app/src/main/java/org/isoron/uhabits/models/ScoreList.java index a8d797233..d3f5da046 100644 --- a/app/src/main/java/org/isoron/uhabits/models/ScoreList.java +++ b/app/src/main/java/org/isoron/uhabits/models/ScoreList.java @@ -128,7 +128,7 @@ public abstract class ScoreList implements Iterable public void writeCSV(Writer out) throws IOException { computeAll(); - SimpleDateFormat dateFormat = DateUtils.getCSVDateFormat(); + SimpleDateFormat dateFormat = DateFormats.getCSVDateFormat(); for (Score s : this) { diff --git a/app/src/main/java/org/isoron/uhabits/models/WeekdayList.java b/app/src/main/java/org/isoron/uhabits/models/WeekdayList.java new file mode 100644 index 000000000..5b6762ead --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/models/WeekdayList.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * 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 . + */ + +package org.isoron.uhabits.models; + +import java.util.*; + +public class WeekdayList +{ + public static WeekdayList EVERY_DAY = new WeekdayList(127); + + private final boolean[] weekdays; + + public WeekdayList(int packedList) + { + weekdays = new boolean[7]; + int current = 1; + + for (int i = 0; i < 7; i++) + { + if ((packedList & current) != 0) weekdays[i] = true; + current = current << 1; + } + } + + public WeekdayList(boolean weekdays[]) + { + this.weekdays = Arrays.copyOf(weekdays, 7); + } + + public boolean[] toArray() + { + return weekdays; + } + + public int toInteger() + { + int packedList = 0; + int current = 1; + + for (int i = 0; i < 7; i++) + { + if (weekdays[i]) packedList |= current; + current = current << 1; + } + + return packedList; + } +} diff --git a/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java b/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java index 35a0873f4..2150a14fb 100644 --- a/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java +++ b/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java @@ -154,7 +154,7 @@ public class HabitRecord extends Model implements SQLiteRecord Reminder reminder = model.getReminder(); this.reminderHour = reminder.getHour(); this.reminderMin = reminder.getMinute(); - this.reminderDays = reminder.getDays(); + this.reminderDays = reminder.getDays().toInteger(); } } @@ -186,8 +186,8 @@ public class HabitRecord extends Model implements SQLiteRecord if (reminderHour != null && reminderMin != null) { - habit.setReminder( - new Reminder(reminderHour, reminderMin, reminderDays)); + habit.setReminder(new Reminder(reminderHour, reminderMin, + new WeekdayList(reminderDays))); } } diff --git a/app/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java b/app/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java index fecc4642d..837829e51 100644 --- a/app/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java +++ b/app/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java @@ -241,8 +241,7 @@ public class ReminderReceiver extends BroadcastReceiver Long timestamp = intent.getLongExtra("timestamp", DateUtils.getStartOfToday()); - boolean reminderDays[] = - DateUtils.unpackWeekdayList(reminder.getDays()); + boolean reminderDays[] = reminder.getDays().toArray(); int weekday = DateUtils.getWeekday(timestamp); return reminderDays[weekday]; diff --git a/app/src/main/java/org/isoron/uhabits/ui/BaseSystem.java b/app/src/main/java/org/isoron/uhabits/ui/BaseSystem.java index 3b8ebac52..6a0b381a2 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/BaseSystem.java +++ b/app/src/main/java/org/isoron/uhabits/ui/BaseSystem.java @@ -26,7 +26,6 @@ import android.view.*; import org.isoron.uhabits.*; import org.isoron.uhabits.models.*; -import org.isoron.uhabits.tasks.*; import org.isoron.uhabits.utils.*; import java.io.*; @@ -72,7 +71,7 @@ public class BaseSystem @NonNull public File dumpBugReportToFile() throws IOException { - String date = DateUtils.getBackupDateFormat().format( + String date = DateFormats.getBackupDateFormat().format( DateUtils.getLocalTime()); if (context == null) throw new RuntimeException( diff --git a/app/src/main/java/org/isoron/uhabits/ui/common/views/FrequencyChart.java b/app/src/main/java/org/isoron/uhabits/ui/common/views/FrequencyChart.java index 8f34b7a26..231d71bcc 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/common/views/FrequencyChart.java +++ b/app/src/main/java/org/isoron/uhabits/ui/common/views/FrequencyChart.java @@ -281,8 +281,8 @@ public class FrequencyChart extends ScrollableChart private void initDateFormats() { - dfMonth = DateUtils.getDateFormat("MMM"); - dfYear = DateUtils.getDateFormat("yyyy"); + dfMonth = DateFormats.fromSkeleton("MMM"); + dfYear = DateFormats.fromSkeleton("yyyy"); } private void initRects() diff --git a/app/src/main/java/org/isoron/uhabits/ui/common/views/HistoryChart.java b/app/src/main/java/org/isoron/uhabits/ui/common/views/HistoryChart.java index 0027d41b2..2a0cd7eda 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/common/views/HistoryChart.java +++ b/app/src/main/java/org/isoron/uhabits/ui/common/views/HistoryChart.java @@ -385,8 +385,8 @@ public class HistoryChart extends ScrollableChart private void initDateFormats() { - dfMonth = DateUtils.getDateFormat("MMM"); - dfYear = DateUtils.getDateFormat("yyyy"); + dfMonth = DateFormats.fromSkeleton("MMM"); + dfYear = DateFormats.fromSkeleton("yyyy"); } private void initRects() diff --git a/app/src/main/java/org/isoron/uhabits/ui/common/views/ScoreChart.java b/app/src/main/java/org/isoron/uhabits/ui/common/views/ScoreChart.java index 969be04de..db3501470 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/common/views/ScoreChart.java +++ b/app/src/main/java/org/isoron/uhabits/ui/common/views/ScoreChart.java @@ -412,9 +412,9 @@ public class ScoreChart extends ScrollableChart private void initDateFormats() { - dfYear = DateUtils.getDateFormat("yyyy"); - dfMonth = DateUtils.getDateFormat("MMM"); - dfDay = DateUtils.getDateFormat("d"); + dfYear = DateFormats.fromSkeleton("yyyy"); + dfMonth = DateFormats.fromSkeleton("MMM"); + dfDay = DateFormats.fromSkeleton("d"); } private void initPaints() diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/edit/BaseDialog.java b/app/src/main/java/org/isoron/uhabits/ui/habits/edit/BaseDialog.java index 656c3d163..c87694ccd 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/edit/BaseDialog.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/edit/BaseDialog.java @@ -31,7 +31,6 @@ import org.isoron.uhabits.*; import org.isoron.uhabits.commands.*; import org.isoron.uhabits.models.*; import org.isoron.uhabits.ui.common.dialogs.*; -import org.isoron.uhabits.utils.DateUtils; import org.isoron.uhabits.utils.*; import java.util.*; @@ -102,7 +101,7 @@ public abstract class BaseDialog extends AppCompatDialogFragment Reminder reminder = modifiedHabit.getReminder(); outState.putInt("reminderMin", reminder.getMinute()); outState.putInt("reminderHour", reminder.getHour()); - outState.putInt("reminderDays", reminder.getDays()); + outState.putInt("reminderDays", reminder.getDays().toInteger()); } } @@ -125,7 +124,8 @@ public abstract class BaseDialog extends AppCompatDialogFragment if (hour >= 0 && minute >= 0) { - Reminder reminder = new Reminder(hour, minute, days); + Reminder reminder = + new Reminder(hour, minute, new WeekdayList(days)); modifiedHabit.setReminder(reminder); } } @@ -173,7 +173,7 @@ public abstract class BaseDialog extends AppCompatDialogFragment WeekdayPickerDialog dialog = new WeekdayPickerDialog(); dialog.setListener(new OnWeekdaysPickedListener()); - dialog.setSelectedDays(DateUtils.unpackWeekdayList(reminder.getDays())); + dialog.setSelectedDays(reminder.getDays().toArray()); dialog.show(getFragmentManager(), "weekdayPicker"); } @@ -215,7 +215,7 @@ public abstract class BaseDialog extends AppCompatDialogFragment public void onTimeSet(RadialPickerLayout view, int hour, int minute) { Reminder reminder = - new Reminder(hour, minute, DateUtils.ALL_WEEK_DAYS); + new Reminder(hour, minute, WeekdayList.EVERY_DAY); modifiedHabit.setReminder(reminder); helper.populateReminderFields(modifiedHabit); } @@ -232,7 +232,7 @@ public abstract class BaseDialog extends AppCompatDialogFragment Reminder oldReminder = modifiedHabit.getReminder(); modifiedHabit.setReminder( new Reminder(oldReminder.getHour(), oldReminder.getMinute(), - DateUtils.packWeekdayList(selectedDays))); + new WeekdayList(selectedDays))); helper.populateReminderFields(modifiedHabit); } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/edit/BaseDialogHelper.java b/app/src/main/java/org/isoron/uhabits/ui/habits/edit/BaseDialogHelper.java index 3cad2ae8d..bca53f0f2 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/edit/BaseDialogHelper.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/edit/BaseDialogHelper.java @@ -144,7 +144,7 @@ public class BaseDialogHelper tvReminderTime.setText(time); llReminderDays.setVisibility(View.VISIBLE); - boolean weekdays[] = DateUtils.unpackWeekdayList(reminder.getDays()); + boolean weekdays[] = reminder.getDays().toArray(); tvReminderDays.setText( DateUtils.formatWeekdayList(frag.getContext(), weekdays)); } diff --git a/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java b/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java index 4ef5ae48f..9955b78cd 100644 --- a/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java +++ b/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java @@ -109,7 +109,7 @@ public abstract class DatabaseUtils { File db = getDatabaseFile(); - SimpleDateFormat dateFormat = DateUtils.getBackupDateFormat(); + SimpleDateFormat dateFormat = DateFormats.getBackupDateFormat(); String date = dateFormat.format(DateUtils.getLocalTime()); File dbCopy = new File( String.format("%s/Loop Habits Backup %s.db", dir.getAbsolutePath(), diff --git a/app/src/main/java/org/isoron/uhabits/utils/DateFormats.java b/app/src/main/java/org/isoron/uhabits/utils/DateFormats.java new file mode 100644 index 000000000..fac0d63bd --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/utils/DateFormats.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * 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 . + */ + +package org.isoron.uhabits.utils; + +import android.support.annotation.*; + +import java.text.*; +import java.util.*; + +import static android.os.Build.VERSION.*; +import static android.os.Build.VERSION_CODES.*; +import static android.text.format.DateFormat.*; + +public class DateFormats +{ + @NonNull + private static SimpleDateFormat fromSkeleton(@NonNull String skeleton, + @NonNull Locale locale) + { + SimpleDateFormat df = new SimpleDateFormat(skeleton, locale); + df.setTimeZone(TimeZone.getTimeZone("UTC")); + return df; + } + + @NonNull + public static SimpleDateFormat fromSkeleton(@NonNull String skeleton) + { + Locale locale = Locale.getDefault(); + + if (SDK_INT >= JELLY_BEAN) + skeleton = getBestDateTimePattern(locale, skeleton); + + return fromSkeleton(skeleton, locale); + } + + public static SimpleDateFormat getBackupDateFormat() + { + return fromSkeleton("yyyy-MM-dd HHmmss", Locale.US); + } + + public static SimpleDateFormat getCSVDateFormat() + { + return fromSkeleton("yyyy-MM-dd", Locale.US); + } +} diff --git a/app/src/main/java/org/isoron/uhabits/utils/DateUtils.java b/app/src/main/java/org/isoron/uhabits/utils/DateUtils.java index c28128387..245ac9f42 100644 --- a/app/src/main/java/org/isoron/uhabits/utils/DateUtils.java +++ b/app/src/main/java/org/isoron/uhabits/utils/DateUtils.java @@ -19,21 +19,17 @@ package org.isoron.uhabits.utils; -import android.content.Context; -import android.text.format.DateFormat; +import android.content.*; +import android.text.format.*; -import org.isoron.uhabits.R; +import org.isoron.uhabits.*; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.Locale; -import java.util.TimeZone; +import java.util.*; + +import static java.util.Calendar.*; public abstract class DateUtils { - public static int ALL_WEEK_DAYS = 127; private static Long fixedLocalTime = null; @@ -44,11 +40,9 @@ public abstract class DateUtils public static String formatHeaderDate(GregorianCalendar day) { - String dayOfMonth = - Integer.toString(day.get(GregorianCalendar.DAY_OF_MONTH)); - String dayOfWeek = day.getDisplayName(GregorianCalendar.DAY_OF_WEEK, - GregorianCalendar.SHORT, Locale.getDefault()); - + Locale locale = Locale.getDefault(); + String dayOfMonth = Integer.toString(day.get(DAY_OF_MONTH)); + String dayOfWeek = day.getDisplayName(DAY_OF_WEEK, SHORT, locale); return dayOfWeek + "\n" + dayOfMonth; } @@ -94,24 +88,6 @@ public abstract class DateUtils return buffer.toString(); } - public static SimpleDateFormat getBackupDateFormat() - { - SimpleDateFormat dateFormat = - new SimpleDateFormat("yyyy-MM-dd HHmmss", Locale.US); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - - return dateFormat; - } - - public static SimpleDateFormat getCSVDateFormat() - { - SimpleDateFormat dateFormat = - new SimpleDateFormat("yyyy-MM-dd", Locale.US); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - - return dateFormat; - } - public static GregorianCalendar getCalendar(long timestamp) { GregorianCalendar day = @@ -120,34 +96,18 @@ public abstract class DateUtils return day; } - public static SimpleDateFormat getDateFormat(String skeleton) - { - String pattern; - Locale locale = Locale.getDefault(); - - if (android.os.Build.VERSION.SDK_INT >= - android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) - pattern = DateFormat.getBestDateTimePattern(locale, skeleton); - else pattern = skeleton; - - SimpleDateFormat format = new SimpleDateFormat(pattern, locale); - format.setTimeZone(TimeZone.getTimeZone("UTC")); - - return format; - } - public static String[] getDayNames(int format) { String[] wdays = new String[7]; Calendar day = new GregorianCalendar(); - day.set(GregorianCalendar.DAY_OF_WEEK, Calendar.SATURDAY); + day.set(DAY_OF_WEEK, Calendar.SATURDAY); for (int i = 0; i < wdays.length; i++) { - wdays[i] = day.getDisplayName(GregorianCalendar.DAY_OF_WEEK, format, - Locale.getDefault()); - day.add(GregorianCalendar.DAY_OF_MONTH, 1); + wdays[i] = + day.getDisplayName(DAY_OF_WEEK, format, Locale.getDefault()); + day.add(DAY_OF_MONTH, 1); } return wdays; @@ -171,14 +131,12 @@ public abstract class DateUtils String[] days = new String[7]; Calendar calendar = new GregorianCalendar(); - calendar.set(GregorianCalendar.DAY_OF_WEEK, - calendar.getFirstDayOfWeek()); + calendar.set(DAY_OF_WEEK, calendar.getFirstDayOfWeek()); for (int i = 0; i < days.length; i++) { - days[i] = - calendar.getDisplayName(GregorianCalendar.DAY_OF_WEEK, format, - Locale.getDefault()); - calendar.add(GregorianCalendar.DAY_OF_MONTH, 1); + days[i] = calendar.getDisplayName(DAY_OF_WEEK, format, + Locale.getDefault()); + calendar.add(DAY_OF_MONTH, 1); } return days; @@ -192,12 +150,11 @@ public abstract class DateUtils { Integer[] dayNumbers = new Integer[7]; Calendar calendar = new GregorianCalendar(); - calendar.set(GregorianCalendar.DAY_OF_WEEK, - calendar.getFirstDayOfWeek()); + calendar.set(DAY_OF_WEEK, calendar.getFirstDayOfWeek()); for (int i = 0; i < dayNumbers.length; i++) { - dayNumbers[i] = calendar.get(GregorianCalendar.DAY_OF_WEEK); - calendar.add(GregorianCalendar.DAY_OF_MONTH, 1); + dayNumbers[i] = calendar.get(DAY_OF_WEEK); + calendar.add(DAY_OF_MONTH, 1); } return dayNumbers; } @@ -209,7 +166,7 @@ public abstract class DateUtils public static String[] getShortDayNames() { - return getDayNames(GregorianCalendar.SHORT); + return getDayNames(SHORT); } public static long getStartOfDay(long timestamp) @@ -230,7 +187,7 @@ public abstract class DateUtils public static int getWeekday(long timestamp) { GregorianCalendar day = getCalendar(timestamp); - return day.get(GregorianCalendar.DAY_OF_WEEK) % 7; + return day.get(DAY_OF_WEEK) % 7; } /** @@ -246,20 +203,6 @@ public abstract class DateUtils return number % 7; } - public static Integer packWeekdayList(boolean weekday[]) - { - int list = 0; - int current = 1; - - for (int i = 0; i < 7; i++) - { - if (weekday[i]) list |= current; - current = current << 1; - } - - return list; - } - public static void setFixedLocalTime(Long timestamp) { fixedLocalTime = timestamp; @@ -279,12 +222,12 @@ public abstract class DateUtils switch (field) { case MONTH: - cal.set(Calendar.DAY_OF_MONTH, 1); + cal.set(DAY_OF_MONTH, 1); return cal.getTimeInMillis(); case WEEK_NUMBER: int firstWeekday = cal.getFirstDayOfWeek(); - int weekday = cal.get(Calendar.DAY_OF_WEEK); + int weekday = cal.get(DAY_OF_WEEK); int delta = weekday - firstWeekday; if (delta < 0) delta += 7; cal.add(Calendar.DAY_OF_YEAR, -delta); @@ -292,13 +235,13 @@ public abstract class DateUtils case QUARTER: int quarter = cal.get(Calendar.MONTH) / 3; - cal.set(Calendar.DAY_OF_MONTH, 1); + cal.set(DAY_OF_MONTH, 1); cal.set(Calendar.MONTH, quarter * 3); return cal.getTimeInMillis(); case YEAR: cal.set(Calendar.MONTH, Calendar.JANUARY); - cal.set(Calendar.DAY_OF_MONTH, 1); + cal.set(DAY_OF_MONTH, 1); return cal.getTimeInMillis(); default: @@ -306,20 +249,6 @@ public abstract class DateUtils } } - public static boolean[] unpackWeekdayList(int list) - { - boolean[] weekday = new boolean[7]; - int current = 1; - - for (int i = 0; i < 7; i++) - { - if ((list & current) != 0) weekday[i] = true; - current = current << 1; - } - - return weekday; - } - public enum TruncateField { MONTH, WEEK_NUMBER, YEAR, QUARTER diff --git a/app/src/test/java/org/isoron/uhabits/models/HabitListTest.java b/app/src/test/java/org/isoron/uhabits/models/HabitListTest.java index eaef8c0ad..f79b971f0 100644 --- a/app/src/test/java/org/isoron/uhabits/models/HabitListTest.java +++ b/app/src/test/java/org/isoron/uhabits/models/HabitListTest.java @@ -21,7 +21,6 @@ package org.isoron.uhabits.models; import org.hamcrest.*; import org.isoron.uhabits.*; -import org.isoron.uhabits.utils.*; import org.junit.*; import java.io.*; @@ -59,7 +58,7 @@ public class HabitListTest extends BaseUnitTest allHabits.add(habit); if (i % 3 == 0) - habit.setReminder(new Reminder(8, 30, DateUtils.ALL_WEEK_DAYS)); + habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY)); } habitsArray.get(0).setArchived(true); diff --git a/app/src/test/java/org/isoron/uhabits/models/HabitTest.java b/app/src/test/java/org/isoron/uhabits/models/HabitTest.java index 5b39641db..6b73766f3 100644 --- a/app/src/test/java/org/isoron/uhabits/models/HabitTest.java +++ b/app/src/test/java/org/isoron/uhabits/models/HabitTest.java @@ -19,8 +19,7 @@ package org.isoron.uhabits.models; -import org.isoron.uhabits.BaseUnitTest; -import org.isoron.uhabits.utils.DateUtils; +import org.isoron.uhabits.*; import org.junit.Test; import static org.hamcrest.CoreMatchers.equalTo; @@ -53,7 +52,7 @@ public class HabitTest extends BaseUnitTest model.setArchived(true); model.setColor(0); model.setFrequency(new Frequency(10, 20)); - model.setReminder(new Reminder(8, 30, 1)); + model.setReminder(new Reminder(8, 30, new WeekdayList(1))); Habit habit = new Habit(); habit.copyFrom(model); @@ -93,7 +92,7 @@ public class HabitTest extends BaseUnitTest Habit h = new Habit(); assertThat(h.hasReminder(), is(false)); - h.setReminder(new Reminder(8, 30, DateUtils.ALL_WEEK_DAYS)); + h.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY)); assertThat(h.hasReminder(), is(true)); h.clearReminder(); diff --git a/app/src/test/java/org/isoron/uhabits/models/ScoreListTest.java b/app/src/test/java/org/isoron/uhabits/models/ScoreListTest.java index 489506e61..1305a2426 100644 --- a/app/src/test/java/org/isoron/uhabits/models/ScoreListTest.java +++ b/app/src/test/java/org/isoron/uhabits/models/ScoreListTest.java @@ -20,7 +20,7 @@ package org.isoron.uhabits.models; import org.isoron.uhabits.BaseUnitTest; -import org.isoron.uhabits.utils.DateUtils; +import org.isoron.uhabits.utils.*; import org.junit.Before; import org.junit.Test; @@ -177,7 +177,7 @@ public class ScoreListTest extends BaseUnitTest private void log(List list) { - SimpleDateFormat df = DateUtils.getCSVDateFormat(); + SimpleDateFormat df = DateFormats.getCSVDateFormat(); for (Score s : list) log("%s %d", df.format(new Date(s.getTimestamp())), s.getValue()); } diff --git a/app/src/test/java/org/isoron/uhabits/models/WeekdayListTest.java b/app/src/test/java/org/isoron/uhabits/models/WeekdayListTest.java new file mode 100644 index 000000000..75ef1afd9 --- /dev/null +++ b/app/src/test/java/org/isoron/uhabits/models/WeekdayListTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * 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 . + */ + +package org.isoron.uhabits.models; + +import org.isoron.uhabits.*; +import org.junit.*; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.core.IsEqual.*; + +public class WeekdayListTest extends BaseUnitTest +{ + @Test + public void test() + { + int daysInt = 124; + boolean[] daysArray = new boolean[]{ + false, false, true, true, true, true, true + }; + + WeekdayList list = new WeekdayList(daysArray); + assertThat(list.toArray(), equalTo(daysArray)); + assertThat(list.toInteger(), equalTo(daysInt)); + + list = new WeekdayList(daysInt); + assertThat(list.toArray(), equalTo(daysArray)); + assertThat(list.toInteger(), equalTo(daysInt)); + } +} diff --git a/app/src/test/java/org/isoron/uhabits/utils/DateUtilsTest.java b/app/src/test/java/org/isoron/uhabits/utils/DateUtilsTest.java index b3b26ecbc..ae46b3c0f 100644 --- a/app/src/test/java/org/isoron/uhabits/utils/DateUtilsTest.java +++ b/app/src/test/java/org/isoron/uhabits/utils/DateUtilsTest.java @@ -19,21 +19,27 @@ package org.isoron.uhabits.utils; -import org.isoron.uhabits.BaseUnitTest; -import org.junit.Test; +import org.isoron.uhabits.*; +import org.junit.*; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.TimeZone; +import java.text.*; +import java.util.*; +import static java.util.Calendar.*; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.*; public class DateUtilsTest extends BaseUnitTest { + @Test + public void testFormatHeaderDate() + { + long timestamp = timestamp(2015, DECEMBER, 31); + GregorianCalendar date = DateUtils.getCalendar(timestamp); + String formatted = DateUtils.formatHeaderDate(date); + assertThat(formatted, equalTo("Thu\n31")); + } + @Test public void testTruncate_dayOfWeek() { @@ -72,10 +78,10 @@ public class DateUtilsTest extends BaseUnitTest assertThat(DateUtils.truncate(field, t1), equalTo(expected)); assertThat(DateUtils.truncate(field, t2), equalTo(expected)); - expected = timestamp(2016, Calendar.DECEMBER, 1); - t0 = timestamp(2016, Calendar.DECEMBER, 1); - t1 = timestamp(2016, Calendar.DECEMBER, 15); - t2 = timestamp(2016, Calendar.DECEMBER, 31); + expected = timestamp(2016, DECEMBER, 1); + t0 = timestamp(2016, DECEMBER, 1); + t1 = timestamp(2016, DECEMBER, 15); + t2 = timestamp(2016, DECEMBER, 31); assertThat(DateUtils.truncate(field, t0), equalTo(expected)); assertThat(DateUtils.truncate(field, t1), equalTo(expected)); @@ -87,19 +93,19 @@ public class DateUtilsTest extends BaseUnitTest { DateUtils.TruncateField field = DateUtils.TruncateField.QUARTER; - long expected = timestamp(2016, Calendar.JANUARY, 1); - long t0 = timestamp(2016, Calendar.JANUARY, 20); - long t1 = timestamp(2016, Calendar.FEBRUARY, 15); - long t2 = timestamp(2016, Calendar.MARCH, 30); + long expected = timestamp(2016, JANUARY, 1); + long t0 = timestamp(2016, JANUARY, 20); + long t1 = timestamp(2016, FEBRUARY, 15); + long t2 = timestamp(2016, MARCH, 30); assertThat(DateUtils.truncate(field, t0), equalTo(expected)); assertThat(DateUtils.truncate(field, t1), equalTo(expected)); assertThat(DateUtils.truncate(field, t2), equalTo(expected)); - expected = timestamp(2016, Calendar.APRIL, 1); - t0 = timestamp(2016, Calendar.APRIL, 1); - t1 = timestamp(2016, Calendar.MAY, 30); - t2 = timestamp(2016, Calendar.JUNE, 20); + expected = timestamp(2016, APRIL, 1); + t0 = timestamp(2016, APRIL, 1); + t1 = timestamp(2016, MAY, 30); + t2 = timestamp(2016, JUNE, 20); assertThat(DateUtils.truncate(field, t0), equalTo(expected)); assertThat(DateUtils.truncate(field, t1), equalTo(expected)); @@ -111,36 +117,36 @@ public class DateUtilsTest extends BaseUnitTest { DateUtils.TruncateField field = DateUtils.TruncateField.YEAR; - long expected = timestamp(2016, Calendar.JANUARY, 1); - long t0 = timestamp(2016, Calendar.JANUARY, 1); - long t1 = timestamp(2016, Calendar.FEBRUARY, 25); - long t2 = timestamp(2016, Calendar.DECEMBER, 31); + long expected = timestamp(2016, JANUARY, 1); + long t0 = timestamp(2016, JANUARY, 1); + long t1 = timestamp(2016, FEBRUARY, 25); + long t2 = timestamp(2016, DECEMBER, 31); assertThat(DateUtils.truncate(field, t0), equalTo(expected)); assertThat(DateUtils.truncate(field, t1), equalTo(expected)); assertThat(DateUtils.truncate(field, t2), equalTo(expected)); - expected = timestamp(2017, Calendar.JANUARY, 1); - t0 = timestamp(2017, Calendar.JANUARY, 1); - t1 = timestamp(2017, Calendar.MAY, 30); - t2 = timestamp(2017, Calendar.DECEMBER, 31); + expected = timestamp(2017, JANUARY, 1); + t0 = timestamp(2017, JANUARY, 1); + t1 = timestamp(2017, MAY, 30); + t2 = timestamp(2017, DECEMBER, 31); assertThat(DateUtils.truncate(field, t0), equalTo(expected)); assertThat(DateUtils.truncate(field, t1), equalTo(expected)); assertThat(DateUtils.truncate(field, t2), equalTo(expected)); } - private void log(long timestamp) - { - DateFormat df = SimpleDateFormat.getDateTimeInstance(); - df.setTimeZone(TimeZone.getTimeZone("GMT")); - log("%s", df.format(new Date(timestamp))); - } - public long timestamp(int year, int month, int day) { GregorianCalendar cal = DateUtils.getStartOfTodayCalendar(); cal.set(year, month, day); return cal.getTimeInMillis(); } + + private void log(long timestamp) + { + DateFormat df = SimpleDateFormat.getDateTimeInstance(); + df.setTimeZone(TimeZone.getTimeZone("GMT")); + log("%s", df.format(new Date(timestamp))); + } } diff --git a/app/src/test/java/org/isoron/uhabits/utils/ReminderSchedulerTest.java b/app/src/test/java/org/isoron/uhabits/utils/ReminderSchedulerTest.java index d6171c7b2..4f71f6bd3 100644 --- a/app/src/test/java/org/isoron/uhabits/utils/ReminderSchedulerTest.java +++ b/app/src/test/java/org/isoron/uhabits/utils/ReminderSchedulerTest.java @@ -52,7 +52,7 @@ public class ReminderSchedulerTest extends BaseUnitTest long atTime = 1422617400000L; // 11:30 jan 30, 2015 (UTC) long expectedCheckmarkTime = 1422576000000L; // 00:00 jan 27, 2015 (UTC) - habit.setReminder(new Reminder(8, 30, DateUtils.ALL_WEEK_DAYS)); + habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY)); scheduleAndVerify(atTime, expectedCheckmarkTime, atTime); } @@ -65,7 +65,7 @@ public class ReminderSchedulerTest extends BaseUnitTest long expectedCheckmarkTime = 1422230400000L; // 00:00 jan 26, 2015 (UTC) long expectedReminderTime = 1422261000000L; // 08:30 jan 26, 2015 (UTC) - habit.setReminder(new Reminder(8, 30, DateUtils.ALL_WEEK_DAYS)); + habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY)); scheduleAndVerify(null, expectedCheckmarkTime, expectedReminderTime); } @@ -79,10 +79,10 @@ public class ReminderSchedulerTest extends BaseUnitTest fixtures.purgeHabits(); Habit h1 = fixtures.createEmptyHabit(); - h1.setReminder(new Reminder(8, 30, DateUtils.ALL_WEEK_DAYS)); + h1.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY)); Habit h2 = fixtures.createEmptyHabit(); - h2.setReminder(new Reminder(18, 30, DateUtils.ALL_WEEK_DAYS)); + h2.setReminder(new Reminder(18, 30, WeekdayList.EVERY_DAY)); fixtures.createEmptyHabit(); @@ -102,7 +102,7 @@ public class ReminderSchedulerTest extends BaseUnitTest long expectedCheckmarkTime = 1453852800000L; // 00:00 jan 27, 2016 (UTC) long expectedReminderTime = 1453883400000L; // 08:30 jan 27, 2016 (UTC) - habit.setReminder(new Reminder(8, 30, DateUtils.ALL_WEEK_DAYS)); + habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY)); scheduleAndVerify(null, expectedCheckmarkTime, expectedReminderTime); }