diff --git a/CHANGELOG.md b/CHANGELOG.md index f17e61d08..1e99f3502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Improved calculation of streaks for non-daily habits: performing habits on irregular weekdays will no longer break your streak. * Many more colors to choose from (now 20 in total). * Ability to customize how transparent the widgets are on your home screen. +* Ability to customize the first day of the week. * Yes/No buttons on notifications, instead of just "Check". * Automatic dark theme according to phone settings (Android 10). * 25% smaller APK size and much smaller backup files. diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/ScoreChartTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/ScoreChartTest.java index 610631a30..759d2e714 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/ScoreChartTest.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/ScoreChartTest.java @@ -29,6 +29,8 @@ import org.isoron.uhabits.utils.*; import org.junit.*; import org.junit.runner.*; +import java.util.*; + @RunWith(AndroidJUnit4.class) @MediumTest public class ScoreChartTest extends BaseViewTest @@ -80,7 +82,7 @@ public class ScoreChartTest extends BaseViewTest @Test public void testRender_withMonthlyBucket() throws Throwable { - view.setScores(habit.getScores().groupBy(DateUtils.TruncateField.MONTH)); + view.setScores(habit.getScores().groupBy(DateUtils.TruncateField.MONTH, Calendar.SUNDAY)); view.setBucketSize(30); view.invalidate(); @@ -97,7 +99,7 @@ public class ScoreChartTest extends BaseViewTest @Test public void testRender_withYearlyBucket() throws Throwable { - view.setScores(habit.getScores().groupBy(DateUtils.TruncateField.YEAR)); + view.setScores(habit.getScores().groupBy(DateUtils.TruncateField.YEAR, Calendar.SUNDAY)); view.setBucketSize(365); view.invalidate(); diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/FrequencyWidgetTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/FrequencyWidgetTest.java index 482d06a32..6739322ce 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/FrequencyWidgetTest.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/FrequencyWidgetTest.java @@ -28,6 +28,8 @@ import org.isoron.uhabits.core.models.*; import org.junit.*; import org.junit.runner.*; +import java.util.*; + @RunWith(AndroidJUnit4.class) @MediumTest public class FrequencyWidgetTest extends BaseViewTest @@ -45,7 +47,7 @@ public class FrequencyWidgetTest extends BaseViewTest setTheme(R.style.WidgetTheme); habit = fixtures.createLongHabit(); - FrequencyWidget widget = new FrequencyWidget(targetContext, 0, habit); + FrequencyWidget widget = new FrequencyWidget(targetContext, 0, habit, Calendar.SUNDAY); view = convertToView(widget, 400, 400); } diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/HistoryWidgetTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/HistoryWidgetTest.java index b0fcea14c..bbab26e67 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/HistoryWidgetTest.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/HistoryWidgetTest.java @@ -28,6 +28,8 @@ import org.isoron.uhabits.core.models.*; import org.junit.*; import org.junit.runner.*; +import java.util.*; + @RunWith(AndroidJUnit4.class) @MediumTest public class HistoryWidgetTest extends BaseViewTest @@ -45,7 +47,7 @@ public class HistoryWidgetTest extends BaseViewTest setTheme(R.style.WidgetTheme); habit = fixtures.createLongHabit(); - HistoryWidget widget = new HistoryWidget(targetContext, 0, habit); + HistoryWidget widget = new HistoryWidget(targetContext, 0, habit, Calendar.SUNDAY); view = convertToView(widget, 400, 400); } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/HistoryEditorDialog.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/HistoryEditorDialog.java index 0a76b52fc..1ef2d1555 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/HistoryEditorDialog.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/HistoryEditorDialog.java @@ -30,6 +30,7 @@ import android.util.*; import org.isoron.uhabits.*; import org.isoron.uhabits.activities.common.views.*; import org.isoron.uhabits.core.models.*; +import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.tasks.*; import org.isoron.uhabits.utils.*; @@ -51,6 +52,8 @@ public class HistoryEditorDialog extends AppCompatDialogFragment private TaskRunner taskRunner; + private Preferences prefs; + public HistoryEditorDialog() { this.controller = new Controller() {}; @@ -72,9 +75,11 @@ public class HistoryEditorDialog extends AppCompatDialogFragment (HabitsApplication) getActivity().getApplicationContext(); habitList = app.getComponent().getHabitList(); taskRunner = app.getComponent().getTaskRunner(); + prefs = app.getComponent().getPreferences(); historyChart = new HistoryChart(context); historyChart.setController(controller); + historyChart.setFirstWeekday(prefs.getFirstWeekday()); if (savedInstanceState != null) { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/WeekdayPickerDialog.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/WeekdayPickerDialog.java index 91f2012b9..41b9346c1 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/WeekdayPickerDialog.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/WeekdayPickerDialog.java @@ -29,6 +29,8 @@ import org.isoron.uhabits.*; import org.isoron.uhabits.core.models.*; import org.isoron.uhabits.core.utils.*; +import java.util.*; + /** * Dialog that allows the user to pick one or more days of the week. */ @@ -59,8 +61,9 @@ public class WeekdayPickerDialog extends AppCompatDialogFragment implements AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder .setTitle(R.string.select_weekdays) - .setMultiChoiceItems(DateUtils.getLongDayNames(), selectedDays, - this) + .setMultiChoiceItems(DateUtils.getLongWeekdayNames(Calendar.SATURDAY), + selectedDays, + this) .setPositiveButton(android.R.string.yes, this) .setNegativeButton(android.R.string.cancel, (dialog, which) -> { dismiss(); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.java index 8b6437638..92b4b2935 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.java @@ -69,8 +69,11 @@ public class FrequencyChart extends ScrollableChart @NonNull private HashMap frequency; + private int maxFreq; + private int firstWeekday = Calendar.SUNDAY; + public FrequencyChart(Context context) { super(context); @@ -98,6 +101,12 @@ public class FrequencyChart extends ScrollableChart postInvalidate(); } + public void setFirstWeekday(int firstWeekday) + { + this.firstWeekday = firstWeekday; + postInvalidate(); + } + private int getMaxFreq(HashMap frequency) { int maxValue = 1; @@ -144,7 +153,6 @@ public class FrequencyChart extends ScrollableChart prevRect.setEmpty(); GregorianCalendar currentDate = DateUtils.getStartOfTodayCalendar(); - currentDate.set(Calendar.DAY_OF_MONTH, 1); currentDate.add(Calendar.MONTH, -nColumns + 2 - getDataOffset()); @@ -193,11 +201,11 @@ public class FrequencyChart extends ScrollableChart private void drawColumn(Canvas canvas, RectF rect, GregorianCalendar date) { - Integer values[] = frequency.get(new Timestamp(date)); + Integer[] values = frequency.get(new Timestamp(date)); float rowHeight = rect.height() / 8.0f; prevRect.set(rect); - Integer[] localeWeekdayList = DateUtils.getLocaleWeekdayList(); + int[] localeWeekdayList = DateUtils.getWeekdaySequence(firstWeekday); for (int j = 0; j < localeWeekdayList.length; j++) { rect.set(0, 0, baseSize, baseSize); @@ -233,7 +241,7 @@ public class FrequencyChart extends ScrollableChart pText.setColor(textColor); pGrid.setColor(gridColor); - for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT)) + for (String day : DateUtils.getShortWeekdayNames(firstWeekday)) { canvas.drawText(day, rGrid.right - columnWidth, rGrid.top + rowHeight / 2 + 0.25f * em, pText); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java index f2f0f3414..90370d5dc 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java @@ -93,6 +93,8 @@ public class HistoryChart extends ScrollableChart private boolean isNumerical = false; + private int firstWeekday = Calendar.SUNDAY; + @NonNull private Controller controller; @@ -210,6 +212,12 @@ public class HistoryChart extends ScrollableChart postInvalidate(); } + public void setFirstWeekday(int firstWeekday) + { + this.firstWeekday = firstWeekday; + postInvalidate(); + } + protected void initPaints() { pTextHeader = new Paint(); @@ -293,7 +301,7 @@ public class HistoryChart extends ScrollableChart { float verticalOffset = pTextHeader.getFontSpacing() * 0.4f; - for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT)) + for (String day : DateUtils.getShortWeekdayNames(firstWeekday)) { location.offset(0, columnWidth); canvas.drawText(day, location.left + headerTextOffset, @@ -375,7 +383,7 @@ public class HistoryChart extends ScrollableChart { float width = 0; - for (String w : DateUtils.getLocaleDayNames(Calendar.SHORT)) + for (String w : DateUtils.getShortWeekdayNames(firstWeekday)) width = Math.max(width, pSquareFg.measureText(w)); return width; @@ -473,7 +481,7 @@ public class HistoryChart extends ScrollableChart int realWeekday = DateUtils.getStartOfTodayCalendar().get(Calendar.DAY_OF_WEEK); todayPositionInColumn = - (7 + realWeekday - baseDate.getFirstDayOfWeek()) % 7; + (7 + realWeekday - firstWeekday) % 7; baseDate.add(Calendar.DAY_OF_YEAR, -nDays); baseDate.add(Calendar.DAY_OF_YEAR, -todayPositionInColumn); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.java index 6d9f4bda1..540318556 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.java @@ -28,6 +28,7 @@ import org.isoron.uhabits.*; import org.isoron.uhabits.R; import org.isoron.uhabits.activities.common.views.*; import org.isoron.uhabits.core.models.*; +import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.tasks.*; import org.isoron.uhabits.utils.*; @@ -56,6 +57,9 @@ public class BarCard extends HabitCard private int bucketSize; + @Nullable + private Preferences prefs; + public BarCard(Context context) { super(context); @@ -84,6 +88,12 @@ public class BarCard extends HabitCard private void init() { + Context appContext = getContext().getApplicationContext(); + if (appContext instanceof HabitsApplication) + { + HabitsApplication app = (HabitsApplication) appContext; + prefs = app.getComponent().getPreferences(); + } inflate(getContext(), R.layout.show_habit_bar, this); ButterKnife.bind(this); boolSpinner.setSelection(1); @@ -120,8 +130,11 @@ public class BarCard extends HabitCard { if (isCanceled()) return; List checkmarks; + int firstWeekday = Calendar.SATURDAY; + if (prefs != null) firstWeekday = prefs.getFirstWeekday(); if (bucketSize == 1) checkmarks = habit.getCheckmarks().getAll(); - else checkmarks = habit.getCheckmarks().groupBy(getTruncateField(bucketSize)); + else checkmarks = habit.getCheckmarks().groupBy(getTruncateField(bucketSize), + firstWeekday); chart.setCheckmarks(checkmarks); chart.setBucketSize(bucketSize); } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.java index f5df21b78..ed4824958 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.java @@ -28,6 +28,7 @@ import org.isoron.uhabits.*; import org.isoron.uhabits.R; import org.isoron.uhabits.activities.common.views.*; import org.isoron.uhabits.core.models.*; +import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.tasks.*; import org.isoron.uhabits.utils.*; @@ -43,6 +44,9 @@ public class FrequencyCard extends HabitCard @BindView(R.id.frequencyChart) FrequencyChart chart; + @Nullable + private Preferences prefs; + public FrequencyCard(Context context) { super(context); @@ -63,6 +67,12 @@ public class FrequencyCard extends HabitCard private void init() { + Context appContext = getContext().getApplicationContext(); + if (appContext instanceof HabitsApplication) + { + HabitsApplication app = (HabitsApplication) appContext; + prefs = app.getComponent().getPreferences(); + } inflate(getContext(), R.layout.show_habit_frequency, this); ButterKnife.bind(this); if (isInEditMode()) initEditMode(); @@ -84,6 +94,7 @@ public class FrequencyCard extends HabitCard if (isCanceled()) return; RepetitionList reps = getHabit().getRepetitions(); HashMap frequency = reps.getWeekdayFrequency(); + if(prefs != null) chart.setFirstWeekday(prefs.getFirstWeekday()); chart.setFrequency(frequency); } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCard.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCard.java index f76c50304..74604aa62 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCard.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCard.java @@ -28,6 +28,7 @@ import org.isoron.uhabits.*; import org.isoron.uhabits.R; import org.isoron.uhabits.activities.common.views.*; import org.isoron.uhabits.core.models.*; +import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.tasks.*; import org.isoron.uhabits.utils.*; @@ -41,9 +42,12 @@ public class HistoryCard extends HabitCard @BindView(R.id.title) TextView title; - @NonNull + @Nullable private Controller controller; + @Nullable + private Preferences prefs; + public HistoryCard(Context context) { super(context); @@ -59,16 +63,23 @@ public class HistoryCard extends HabitCard @OnClick(R.id.edit) public void onClickEditButton() { - controller.onEditHistoryButtonClick(); + if(controller != null) controller.onEditHistoryButtonClick(); } - public void setController(@NonNull Controller controller) + public void setController(@Nullable Controller controller) { this.controller = controller; } private void init() { + Context appContext = getContext().getApplicationContext(); + if (appContext instanceof HabitsApplication) + { + HabitsApplication app = (HabitsApplication) appContext; + prefs = app.getComponent().getPreferences(); + } + inflate(getContext(), R.layout.show_habit_history, this); ButterKnife.bind(this); controller = new Controller() {}; @@ -107,7 +118,8 @@ public class HistoryCard extends HabitCard public void doInBackground() { if (isCanceled()) return; - int checkmarks[] = habit.getCheckmarks().getAllValues(); + int[] checkmarks = habit.getCheckmarks().getAllValues(); + if(prefs != null) chart.setFirstWeekday(prefs.getFirstWeekday()); chart.setCheckmarks(checkmarks); } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.java index bb0d01964..cdaabdc3e 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.java @@ -143,9 +143,12 @@ public class ScoreCard extends HabitCard if (isCanceled()) return; List scores; ScoreList scoreList = getHabit().getScores(); + int firstWeekday = Calendar.SATURDAY; + if (prefs != null) firstWeekday = prefs.getFirstWeekday(); + Log.d("ScoreCard", "firstWeekday="+firstWeekday); if (bucketSize == 1) scores = scoreList.toList(); - else scores = scoreList.groupBy(getTruncateField(bucketSize)); + else scores = scoreList.groupBy(getTruncateField(bucketSize), firstWeekday); chart.setScores(scores); chart.setBucketSize(bucketSize); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java index 6d30282b6..966450a6c 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java @@ -32,9 +32,12 @@ import org.isoron.uhabits.R; import org.isoron.uhabits.*; import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.ui.*; +import org.isoron.uhabits.core.utils.*; import org.isoron.uhabits.notifications.*; import org.isoron.uhabits.widgets.*; +import java.util.*; + import static android.media.RingtoneManager.*; import static android.os.Build.VERSION.*; import static org.isoron.uhabits.activities.habits.list.ListHabitsScreenKt.*; @@ -143,6 +146,8 @@ public class SettingsFragment extends PreferenceFragmentCompat devCategory.setVisible(false); } + updateWeekdayPreference(); + if (SDK_INT < Build.VERSION_CODES.O) findPreference("reminderCustomize").setVisible(false); else @@ -154,6 +159,19 @@ public class SettingsFragment extends PreferenceFragmentCompat updateSync(); } + private void updateWeekdayPreference() + { + if (prefs == null) return; + ListPreference weekdayPref = (ListPreference) findPreference("pref_first_weekday"); + int currentFirstWeekday = prefs.getFirstWeekday(); + String[] dayNames = DateUtils.getLongWeekdayNames(Calendar.SATURDAY); + String[] dayValues = {"7", "1", "2", "3", "4", "5", "6"}; + weekdayPref.setEntries(dayNames); + weekdayPref.setEntryValues(dayValues); + weekdayPref.setDefaultValue(Integer.toString(currentFirstWeekday)); + weekdayPref.setSummary(dayNames[currentFirstWeekday % 7]); + } + @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) @@ -163,6 +181,7 @@ public class SettingsFragment extends PreferenceFragmentCompat Log.d("SettingsFragment", "updating widgets"); widgetUpdater.updateWidgets(); } + if (key.equals("pref_first_weekday")) updateWeekdayPreference(); BackupManager.dataChanged("org.isoron.uhabits"); updateSync(); } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/AndroidDateUtils.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/AndroidDateUtils.java index e07f7b708..82d1e56e1 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/AndroidDateUtils.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/AndroidDateUtils.java @@ -41,8 +41,8 @@ public class AndroidDateUtils public static String formatWeekdayList(Context context, boolean weekday[]) { - String shortDayNames[] = org.isoron.uhabits.core.utils.DateUtils.getShortDayNames(); - String longDayNames[] = org.isoron.uhabits.core.utils.DateUtils.getLongDayNames(); + String shortDayNames[] = org.isoron.uhabits.core.utils.DateUtils.getShortWeekdayNames(Calendar.SATURDAY); + String longDayNames[] = org.isoron.uhabits.core.utils.DateUtils.getLongWeekdayNames(Calendar.SATURDAY); StringBuilder buffer = new StringBuilder(); int count = 0; diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java index a4e9bc5da..fec0c2e49 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java @@ -40,6 +40,7 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider private HabitList habits; private Preferences preferences; + private WidgetPreferences widgetPrefs; public static void updateAppWidget(@NonNull AppWidgetManager manager, @@ -195,4 +196,9 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider preferences = app.getComponent().getPreferences(); widgetPrefs = app.getComponent().getWidgetPreferences(); } + + public Preferences getPreferences() + { + return preferences; + } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt index 976783b0e..bdc60a3f6 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt @@ -29,7 +29,8 @@ import org.isoron.uhabits.widgets.views.* class FrequencyWidget( context: Context, widgetId: Int, - private val habit: Habit + private val habit: Habit, + private val firstWeekday: Int ) : BaseWidget(context, widgetId) { override fun getOnClickPendingIntent(context: Context) = @@ -40,6 +41,7 @@ class FrequencyWidget( widgetView.setTitle(habit.name) widgetView.setBackgroundAlpha(preferedBackgroundAlpha) (widgetView.dataView as FrequencyChart).apply { + setFirstWeekday(firstWeekday) setColor(PaletteUtils.getColor(context, habit.color)) setFrequency(habit.repetitions.weekdayFrequency) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidgetProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidgetProvider.kt index 8c724d17e..83aedc39c 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidgetProvider.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidgetProvider.kt @@ -24,7 +24,10 @@ import android.content.* class FrequencyWidgetProvider : BaseWidgetProvider() { override fun getWidgetFromId(context: Context, id: Int): BaseWidget { val habits = getHabitsFromWidgetId(id) - if (habits.size == 1) return FrequencyWidget(context, id, habits[0]) + if (habits.size == 1) return FrequencyWidget(context, + id, + habits[0], + preferences.firstWeekday) else return StackWidget(context, id, StackWidgetType.FREQUENCY, habits) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt index 621df2a4d..9860b3e15 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt @@ -30,7 +30,8 @@ import org.isoron.uhabits.widgets.views.* class HistoryWidget( context: Context, id: Int, - private val habit: Habit + private val habit: Habit, + private val firstWeekday: Int ) : BaseWidget(context, id) { override fun getOnClickPendingIntent(context: Context): PendingIntent { @@ -41,6 +42,7 @@ class HistoryWidget( val widgetView = view as GraphWidgetView widgetView.setBackgroundAlpha(preferedBackgroundAlpha) (widgetView.dataView as HistoryChart).apply { + setFirstWeekday(firstWeekday) setColor(PaletteUtils.getColor(context, habit.color)) setCheckmarks(habit.checkmarks.allValues) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidgetProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidgetProvider.kt index 0f4199b12..fe962ce51 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidgetProvider.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidgetProvider.kt @@ -23,7 +23,10 @@ import android.content.* class HistoryWidgetProvider : BaseWidgetProvider() { override fun getWidgetFromId(context: Context, id: Int): BaseWidget { val habits = getHabitsFromWidgetId(id) - if (habits.size == 1) return HistoryWidget(context, id, habits[0]) + if (habits.size == 1) return HistoryWidget(context, + id, + habits[0], + preferences.firstWeekday) else return StackWidget(context, id, StackWidgetType.HISTORY, habits) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt index 42083a353..93dbf6792 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt @@ -40,7 +40,8 @@ class ScoreWidget( val size = ScoreCard.BUCKET_SIZES[prefs.defaultScoreSpinnerPosition] val scores = when(size) { 1 -> habit.scores.toList() - else -> habit.scores.groupBy(ScoreCard.getTruncateField(size)) + else -> habit.scores.groupBy(ScoreCard.getTruncateField(size), + prefs.firstWeekday) } val widgetView = view as GraphWidgetView diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.java index b753c2c2d..74a4545f2 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.java @@ -9,6 +9,7 @@ import android.widget.*; import org.isoron.uhabits.*; import org.isoron.uhabits.core.models.*; +import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.utils.*; import java.util.*; @@ -87,18 +88,19 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory } @NonNull - private BaseWidget constructWidget(@NonNull Habit habit) + private BaseWidget constructWidget(@NonNull Habit habit, + @NonNull Preferences prefs) { switch (widgetType) { case CHECKMARK: return new CheckmarkWidget(context, widgetId, habit); case FREQUENCY: - return new FrequencyWidget(context, widgetId, habit); + return new FrequencyWidget(context, widgetId, habit, prefs.getFirstWeekday()); case SCORE: return new ScoreWidget(context, widgetId, habit); case HISTORY: - return new HistoryWidget(context, widgetId, habit); + return new HistoryWidget(context, widgetId, habit, prefs.getFirstWeekday()); case STREAKS: return new StreakWidget(context, widgetId, habit); } @@ -136,6 +138,7 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory Log.i("StackRemoteViewsFactory", "onDataSetChanged started"); HabitsApplication app = (HabitsApplication) context.getApplicationContext(); + Preferences prefs = app.getComponent().getPreferences(); HabitList habitList = app.getComponent().getHabitList(); Bundle options = AppWidgetManager.getInstance(context).getAppWidgetOptions(widgetId); ArrayList newRemoteViews = new ArrayList<>(); @@ -147,7 +150,7 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory Habit h = habitList.getById(id); if (h == null) throw new HabitNotFoundException(); - BaseWidget widget = constructWidget(h); + BaseWidget widget = constructWidget(h, prefs); widget.setDimensions(getDimensionsFromOptions(context, options)); RemoteViews landscapeViews = widget.getLandscapeRemoteViews(); diff --git a/android/uhabits-android/src/main/res/values/strings.xml b/android/uhabits-android/src/main/res/values/strings.xml index 90abdcfed..2a724c7da 100644 --- a/android/uhabits-android/src/main/res/values/strings.xml +++ b/android/uhabits-android/src/main/res/values/strings.xml @@ -242,5 +242,6 @@ Database Widget opacity Makes widgets more transparent or more opaque in your home screen. + First day of the week \ No newline at end of file diff --git a/android/uhabits-android/src/main/res/xml/preferences.xml b/android/uhabits-android/src/main/res/xml/preferences.xml index 2656688d3..032dda1d7 100644 --- a/android/uhabits-android/src/main/res/xml/preferences.xml +++ b/android/uhabits-android/src/main/res/xml/preferences.xml @@ -55,6 +55,11 @@ android:title="@string/widget_opacity_title" app:iconSpaceReserved="false" /> + + groupBy(DateUtils.TruncateField field) + public List groupBy(DateUtils.TruncateField field, int firstWeekday) { List checks = getAll(); @@ -422,7 +422,7 @@ public abstract class CheckmarkList for (Checkmark rep : checks) { - Timestamp tt = rep.getTimestamp().truncate(field); + Timestamp tt = rep.getTimestamp().truncate(field, firstWeekday); if (count == 0 || !truncatedTimestamps[count - 1].equals(tt)) truncatedTimestamps[count++] = tt; diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ScoreList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ScoreList.java index 49c1c36fb..c9599671a 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ScoreList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ScoreList.java @@ -129,10 +129,10 @@ public abstract class ScoreList implements Iterable return values; } - public List groupBy(DateUtils.TruncateField field) + public List groupBy(DateUtils.TruncateField field, int firstWeekday) { computeAll(); - HashMap> groups = getGroupedValues(field); + HashMap> groups = getGroupedValues(field, firstWeekday); List scores = groupsToAvgScores(groups); Collections.sort(scores, (s1, s2) -> s2.compareNewer(s1)); return scores; @@ -293,14 +293,18 @@ public abstract class ScoreList implements Iterable } @NonNull - private HashMap> getGroupedValues(DateUtils.TruncateField field) + private HashMap> getGroupedValues(DateUtils.TruncateField field, + int firstWeekday) { HashMap> groups = new HashMap<>(); for (Score s : this) { Timestamp groupTimestamp = new Timestamp( - DateUtils.truncate(field, s.getTimestamp().getUnixTime())); + DateUtils.truncate( + field, + s.getTimestamp().getUnixTime(), + firstWeekday)); if (!groups.containsKey(groupTimestamp)) groups.put(groupTimestamp, new ArrayList<>()); diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Timestamp.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Timestamp.java index e79ef5609..af311d85f 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Timestamp.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Timestamp.java @@ -143,13 +143,17 @@ public final class Timestamp return DateFormats.getCSVDateFormat().format(new Date(unixTime)); } + /** + * Returns an integer corresponding to the day of the week. Saturday maps + * to 0, Sunday maps to 1, and so on. + */ public int getWeekday() { return toCalendar().get(DAY_OF_WEEK) % 7; } - public Timestamp truncate(DateUtils.TruncateField field) + Timestamp truncate(DateUtils.TruncateField field, int firstWeekday) { - return new Timestamp(DateUtils.truncate(field, unixTime)); + return new Timestamp(DateUtils.truncate(field, unixTime, firstWeekday)); } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java index 1a27b7562..c9753b0c0 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java @@ -333,6 +333,19 @@ public class Preferences return Integer.parseInt(storage.getString("pref_widget_opacity", "102")); } + /** + * @return An integer representing the first day of the week. Sunday + * corresponds to 1, Monday to 2, and so on, until Saturday, which is + * represented by 7. By default, this is based on the current system locale, + * unless the user changed this in the settings. + */ + public int getFirstWeekday() + { + String weekday = storage.getString("pref_first_weekday", ""); + if (weekday.isEmpty()) return DateUtils.getFirstWeekdayNumberAccordingToLocale(); + return Integer.parseInt(weekday); + } + public interface Listener { default void onCheckmarkSequenceChanged() diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java index 149af5969..d9f291e33 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java @@ -22,6 +22,7 @@ package org.isoron.uhabits.core.utils; import android.support.annotation.*; import org.isoron.uhabits.core.models.*; +import org.jetbrains.annotations.*; import java.util.*; @@ -73,23 +74,6 @@ public abstract class DateUtils return day; } - private static String[] getDayNames(int format) - { - String[] wdays = new String[7]; - - Calendar day = new GregorianCalendar(); - day.set(DAY_OF_WEEK, Calendar.SATURDAY); - - for (int i = 0; i < wdays.length; i++) - { - wdays[i] = - day.getDisplayName(DAY_OF_WEEK, format, getLocale()); - day.add(DAY_OF_MONTH, 1); - } - - return wdays; - } - public static long getLocalTime() { if (fixedLocalTime != null) return fixedLocalTime; @@ -100,19 +84,25 @@ public abstract class DateUtils } /** - * @return array with weekday names starting according to locale settings, - * e.g. [Mo,Di,Mi,Do,Fr,Sa,So] in Germany + * Returns an array of strings with the names for each day of the week, + * in either SHORT or LONG format. The first entry corresponds to the + * first day of the week, according to the provided argument. + * + * @param format Either GregorianCalendar.SHORT or LONG + * @param firstWeekday An integer representing the first day of the week, + * following java.util.Calendar conventions. That is, + * Saturday corresponds to 7, and Sunday corresponds + * to 1. */ - public static String[] getLocaleDayNames(int format) + @NotNull + private static String[] getWeekdayNames(int format, int firstWeekday) { String[] days = new String[7]; - Calendar calendar = new GregorianCalendar(); - calendar.set(DAY_OF_WEEK, calendar.getFirstDayOfWeek()); - for (int i = 0; i < days.length; i++) - { + calendar.set(DAY_OF_WEEK, firstWeekday); + for (int i = 0; i < days.length; i++) { days[i] = calendar.getDisplayName(DAY_OF_WEEK, format, - getLocale()); + getLocale()); calendar.add(DAY_OF_MONTH, 1); } @@ -120,30 +110,63 @@ public abstract class DateUtils } /** - * @return array with week days numbers starting according to locale - * settings, e.g. [2,3,4,5,6,7,1] in Europe + * Returns a vector of exactly seven integers, where the first integer is + * the provided firstWeekday number, and each subsequent number is the + * previous number plus 1, wrapping back to 1 after 7. For example, + * providing 3 as firstWeekday returns {3,4,5,6,7,1,2} + * + * This function is supposed to be used to construct a sequence of weekday + * number following java.util.Calendar conventions. */ - public static Integer[] getLocaleWeekdayList() + public static int[] getWeekdaySequence(int firstWeekday) { - Integer[] dayNumbers = new Integer[7]; - Calendar calendar = new GregorianCalendar(); - calendar.set(DAY_OF_WEEK, calendar.getFirstDayOfWeek()); - for (int i = 0; i < dayNumbers.length; i++) + return new int[] { - dayNumbers[i] = calendar.get(DAY_OF_WEEK); - calendar.add(DAY_OF_MONTH, 1); - } - return dayNumbers; + (firstWeekday - 1) % 7 + 1, + (firstWeekday) % 7 + 1, + (firstWeekday + 1) % 7 + 1, + (firstWeekday + 2) % 7 + 1, + (firstWeekday + 3) % 7 + 1, + (firstWeekday + 4) % 7 + 1, + (firstWeekday + 5) % 7 + 1, + }; } - public static String[] getLongDayNames() + /** + * @return An integer representing the first day of the week, according to + * the current locale. Sunday corresponds to 1, Monday to 2, and so on, + * until Saturday, which is represented by 7. This is consistent + * with java.util.Calendar constants. + */ + public static int getFirstWeekdayNumberAccordingToLocale() { - return getDayNames(GregorianCalendar.LONG); + return new GregorianCalendar().getFirstDayOfWeek(); } - public static String[] getShortDayNames() + /** + * @return A vector of strings with the long names for the week days, + * according to the current locale. The first entry corresponds to Saturday, + * the second entry corresponds to Monday, and so on. + * + * @param firstWeekday Either Calendar.SATURDAY, Calendar.MONDAY, or other + * weekdays defined in this class. + */ + public static String[] getLongWeekdayNames(int firstWeekday) { - return getDayNames(SHORT); + return getWeekdayNames(GregorianCalendar.LONG, firstWeekday); + } + + /** + * Returns a vector of strings with the short names for the week days, + * according to the current locale. The first entry corresponds to Saturday, + * the second entry corresponds to Monday, and so on. + * + * @param firstWeekday Either Calendar.SATURDAY, Calendar.MONDAY, or other + * weekdays defined in this class. + */ + public static String[] getShortWeekdayNames(int firstWeekday) + { + return getWeekdayNames(GregorianCalendar.SHORT, firstWeekday); } @NonNull @@ -206,10 +229,13 @@ public abstract class DateUtils return Locale.getDefault(); } - public static Long truncate(TruncateField field, long timestamp) + public static Long truncate(TruncateField field, + long timestamp, + int firstWeekday) { GregorianCalendar cal = DateUtils.getCalendar(timestamp); + switch (field) { case MONTH: @@ -217,7 +243,6 @@ public abstract class DateUtils return cal.getTimeInMillis(); case WEEK_NUMBER: - int firstWeekday = cal.getFirstDayOfWeek(); int weekday = cal.get(DAY_OF_WEEK); int delta = weekday - firstWeekday; if (delta < 0) delta += 7; diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/CheckmarkListTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/CheckmarkListTest.java index 66151fd7d..02ad7acf7 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/CheckmarkListTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/CheckmarkListTest.java @@ -388,20 +388,20 @@ public class CheckmarkListTest extends BaseUnitTest Habit habit = fixtures.createLongNumericalHabit(timestamp(2014, JUNE, 1)); CheckmarkList checkmarks = habit.getCheckmarks(); - List byMonth = checkmarks.groupBy(MONTH); + List byMonth = checkmarks.groupBy(MONTH, Calendar.SATURDAY); assertThat(byMonth.size(), equalTo(25)); // from 2013-01-01 to 2015-01-01 assertThat(byMonth.get(0), equalTo(new Checkmark(timestamp(2015, JANUARY, 1), 0))); assertThat(byMonth.get(6), equalTo(new Checkmark(timestamp(2014, JULY, 1), 0))); assertThat(byMonth.get(12), equalTo(new Checkmark(timestamp(2014, JANUARY, 1), 1706))); assertThat(byMonth.get(18), equalTo(new Checkmark(timestamp(2013, JULY, 1), 1379))); - List byQuarter = checkmarks.groupBy(QUARTER); + List byQuarter = checkmarks.groupBy(QUARTER, Calendar.SATURDAY); assertThat(byQuarter.size(), equalTo(9)); // from 2013-Q1 to 2015-Q1 assertThat(byQuarter.get(0), equalTo(new Checkmark(timestamp(2015, JANUARY, 1), 0))); assertThat(byQuarter.get(4), equalTo(new Checkmark(timestamp(2014, JANUARY, 1), 4964))); assertThat(byQuarter.get(8), equalTo(new Checkmark(timestamp(2013, JANUARY, 1), 4975))); - List byYear = checkmarks.groupBy(YEAR); + List byYear = checkmarks.groupBy(YEAR, Calendar.SATURDAY); assertThat(byYear.size(), equalTo(3)); // from 2013 to 2015 assertThat(byYear.get(0), equalTo(new Checkmark(timestamp(2015, JANUARY, 1), 0))); assertThat(byYear.get(1), equalTo(new Checkmark(timestamp(2014, JANUARY, 1), 8227))); diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/ScoreListTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/ScoreListTest.java index 3f2fd8783..0270a7e29 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/ScoreListTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/ScoreListTest.java @@ -150,7 +150,7 @@ public class ScoreListTest extends BaseUnitTest { Habit habit = fixtures.createLongHabit(); List list = - habit.getScores().groupBy(DateUtils.TruncateField.MONTH); + habit.getScores().groupBy(DateUtils.TruncateField.MONTH, Calendar.SATURDAY); assertThat(list.size(), equalTo(5)); assertThat(list.get(0).getValue(), closeTo(0.653659, E)); diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java index cb6a24640..15413dce9 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java @@ -34,6 +34,9 @@ import static org.isoron.uhabits.core.utils.DateUtils.removeTimezone; public class DateUtilsTest extends BaseUnitTest { + + int firstWeekday = SUNDAY; + @Before @Override public void setUp() throws Exception @@ -61,18 +64,29 @@ public class DateUtilsTest extends BaseUnitTest long t1 = unixTime(2015, Calendar.JANUARY, 16); long t2 = unixTime(2015, Calendar.JANUARY, 17); - assertThat(DateUtils.truncate(field, t0), equalTo(expected)); - assertThat(DateUtils.truncate(field, t1), equalTo(expected)); - assertThat(DateUtils.truncate(field, t2), equalTo(expected)); + assertThat(DateUtils.truncate(field, t0, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t1, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t2, firstWeekday), equalTo(expected)); expected = unixTime(2015, Calendar.JANUARY, 18); t0 = unixTime(2015, Calendar.JANUARY, 18); t1 = unixTime(2015, Calendar.JANUARY, 19); t2 = unixTime(2015, Calendar.JANUARY, 24); - assertThat(DateUtils.truncate(field, t0), equalTo(expected)); - assertThat(DateUtils.truncate(field, t1), equalTo(expected)); - assertThat(DateUtils.truncate(field, t2), equalTo(expected)); + assertThat(DateUtils.truncate(field, t0, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t1, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t2, firstWeekday), equalTo(expected)); + + + firstWeekday = WEDNESDAY; + expected = unixTime(2015, Calendar.JANUARY, 7); + t0 = unixTime(2015, Calendar.JANUARY, 7); + t1 = unixTime(2015, Calendar.JANUARY, 9); + t2 = unixTime(2015, Calendar.JANUARY, 13); + + assertThat(DateUtils.truncate(field, t0, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t1, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t2, firstWeekday), equalTo(expected)); } @Test @@ -85,18 +99,18 @@ public class DateUtilsTest extends BaseUnitTest DateUtils.TruncateField field = DateUtils.TruncateField.MONTH; - assertThat(DateUtils.truncate(field, t0), equalTo(expected)); - assertThat(DateUtils.truncate(field, t1), equalTo(expected)); - assertThat(DateUtils.truncate(field, t2), equalTo(expected)); + assertThat(DateUtils.truncate(field, t0, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t1, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t2, firstWeekday), equalTo(expected)); expected = unixTime(2016, DECEMBER, 1); t0 = unixTime(2016, DECEMBER, 1); t1 = unixTime(2016, DECEMBER, 15); t2 = unixTime(2016, DECEMBER, 31); - assertThat(DateUtils.truncate(field, t0), equalTo(expected)); - assertThat(DateUtils.truncate(field, t1), equalTo(expected)); - assertThat(DateUtils.truncate(field, t2), equalTo(expected)); + assertThat(DateUtils.truncate(field, t0, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t1, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t2, firstWeekday), equalTo(expected)); } @Test @@ -109,18 +123,18 @@ public class DateUtilsTest extends BaseUnitTest long t1 = unixTime(2016, FEBRUARY, 15); long t2 = unixTime(2016, MARCH, 30); - assertThat(DateUtils.truncate(field, t0), equalTo(expected)); - assertThat(DateUtils.truncate(field, t1), equalTo(expected)); - assertThat(DateUtils.truncate(field, t2), equalTo(expected)); + assertThat(DateUtils.truncate(field, t0, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t1, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t2, firstWeekday), equalTo(expected)); expected = unixTime(2016, APRIL, 1); t0 = unixTime(2016, APRIL, 1); t1 = unixTime(2016, MAY, 30); t2 = unixTime(2016, JUNE, 20); - assertThat(DateUtils.truncate(field, t0), equalTo(expected)); - assertThat(DateUtils.truncate(field, t1), equalTo(expected)); - assertThat(DateUtils.truncate(field, t2), equalTo(expected)); + assertThat(DateUtils.truncate(field, t0, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t1, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t2, firstWeekday), equalTo(expected)); } @Test @@ -133,18 +147,18 @@ public class DateUtilsTest extends BaseUnitTest long t1 = unixTime(2016, FEBRUARY, 25); long t2 = unixTime(2016, DECEMBER, 31); - assertThat(DateUtils.truncate(field, t0), equalTo(expected)); - assertThat(DateUtils.truncate(field, t1), equalTo(expected)); - assertThat(DateUtils.truncate(field, t2), equalTo(expected)); + assertThat(DateUtils.truncate(field, t0, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t1, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t2, firstWeekday), equalTo(expected)); expected = unixTime(2017, JANUARY, 1); t0 = unixTime(2017, JANUARY, 1); t1 = unixTime(2017, MAY, 30); t2 = unixTime(2017, DECEMBER, 31); - assertThat(DateUtils.truncate(field, t0), equalTo(expected)); - assertThat(DateUtils.truncate(field, t1), equalTo(expected)); - assertThat(DateUtils.truncate(field, t2), equalTo(expected)); + assertThat(DateUtils.truncate(field, t0, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t1, firstWeekday), equalTo(expected)); + assertThat(DateUtils.truncate(field, t2, firstWeekday), equalTo(expected)); } @Test