Skip to content

Commit dbc0d94

Browse files
committed
#7 Allow to have both "BBB" and "BBBB" in one custom pattern. Only the first non empty is shown. Add another Pattern example.
1 parent 9222fc7 commit dbc0d94

File tree

5 files changed

+105
-35
lines changed

5 files changed

+105
-35
lines changed

app/src/androidTest/java/org/andstatus/todoagenda/prefs/DateFormatterTest.java

+38-9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import org.joda.time.DateTime;
99
import org.junit.Test;
1010

11+
import java.text.SimpleDateFormat;
12+
import java.util.Locale;
13+
14+
import static org.andstatus.todoagenda.prefs.dateformat.DateFormatter.toJavaDate;
1115
import static org.junit.Assert.assertEquals;
1216

1317
/**
@@ -16,7 +20,7 @@
1620
public class DateFormatterTest extends BaseWidgetTest {
1721

1822
@Test
19-
public void timeTimeZones() {
23+
public void testTimeZones() {
2024
InstanceSettings settings = getSettings();
2125
settings.clock().setSnapshotMode(SnapshotMode.SNAPSHOT_TIME);
2226
assertNow("2020-02-15T01:00:00.000+08:00");
@@ -58,21 +62,41 @@ public void customPatterns() {
5862
DateTime now = settings.clock().now().withTimeAtStartOfDay().plusHours(1);
5963
provider.setExecutedAt(now);
6064

61-
assertPattern(now, "yyyy-MM-dd b", String.format("%04d-%02d-%02d", now.yearOfEra().get(),
62-
now.monthOfYear().get(), now.dayOfMonth().get()) + " 0");
65+
CharSequence todayText = provider.getContext().getText(R.string.today);
66+
String tomorrowText = provider.getContext().getText(R.string.tomorrow).toString();
67+
String inTwoDaysText = String.format(provider.getContext().getText(R.string.in_N_days).toString(), 2);
68+
69+
String javaPattern = "yyyy-MM-dd";
70+
String javaFormatted = String.format("%04d-%02d-%02d", now.yearOfEra().get(),
71+
now.monthOfYear().get(), now.dayOfMonth().get());
72+
assertEquals(javaFormatted, javaFormatted(javaPattern, now));
73+
assertPattern(now, javaPattern, javaFormatted);
74+
assertPattern(now, javaPattern + " b", javaFormatted + " 0");
75+
assertPattern(now, "BBB " + javaPattern + " b", todayText + " " + javaFormatted);
76+
assertPattern(now.plusDays(1), "BBB " + javaPattern + " b", tomorrowText + " " +
77+
javaFormatted(javaPattern, now.plusDays(1)));
78+
assertPattern(now.plusDays(2), "BBB " + javaPattern + " b",
79+
javaFormatted(javaPattern, now.plusDays(2)) + " 2");
80+
81+
assertPattern(now, "BBB " + javaPattern + " BBBB", todayText + " " + javaFormatted);
82+
assertPattern(now.plusDays(1), "BBB " + javaPattern + " BBBB", tomorrowText + " " +
83+
javaFormatted(javaPattern, now.plusDays(1)));
84+
assertPattern(now.plusDays(2), "BBB " + javaPattern + " BBBB",
85+
javaFormatted(javaPattern, now.plusDays(2)) + " " + inTwoDaysText);
86+
6387
assertPattern(now, "b", "0");
6488
assertPattern(now, "MM-dd bb", String.format("%02d-%02d", now.monthOfYear().get(), now.dayOfMonth().get()) + " 00");
65-
assertPattern(now.plusDays(1), "", "");
89+
assertPattern(now.plusDays(1), "", "(not implemented: " +
90+
DateFormatValue.of(DateFormatType.CUSTOM, "").getSummary(provider.getContext()) + ")");
6691
assertPattern(now.plusDays(1), "b", "1");
6792
assertPattern(now.plusDays(1), "bbb", "001");
68-
CharSequence tomorrowText = provider.getContext().getText(R.string.tomorrow);
69-
assertPattern(now.plusDays(1), "bbbb", tomorrowText.toString());
70-
assertPattern(now.plusDays(1), "BBB", tomorrowText.toString());
71-
assertPattern(now.plusDays(1), "BBBB", tomorrowText.toString());
93+
assertPattern(now.plusDays(1), "bbbb", tomorrowText);
94+
assertPattern(now.plusDays(1), "BBB", tomorrowText);
95+
assertPattern(now.plusDays(1), "BBBB", tomorrowText);
7296
assertPattern(now.plusDays(-2), "BBB", "");
7397
assertPattern(now.plusDays(-2), "BBBB", String.format(provider.getContext().getText(R.string.N_days_ago).toString(), 2));
7498
assertPattern(now.plusDays(2), "BBB", "");
75-
assertPattern(now.plusDays(2), "BBBB", String.format(provider.getContext().getText(R.string.in_N_days).toString(), 2));
99+
assertPattern(now.plusDays(2), "BBBB", inTwoDaysText);
76100
assertPattern(now.plusDays(5), "b", "5");
77101
assertPattern(now.plusDays(5), "bbb", "005");
78102
assertPattern(now.plusDays(5), "bbbb", "5");
@@ -81,6 +105,11 @@ public void customPatterns() {
81105
assertPattern(now.minusDays(5), "bbbb", "-5");
82106
}
83107

108+
private static String javaFormatted(String javaPattern, DateTime date) {
109+
Locale locale = Locale.getDefault();
110+
return new SimpleDateFormat(javaPattern, locale).format(toJavaDate(date));
111+
}
112+
84113
private void assertPattern(DateTime date, String pattern, String expected) {
85114
DateFormatValue format = DateFormatValue.of(DateFormatType.CUSTOM, pattern);
86115
DateTime now = getSettings().clock().now();

app/src/main/java/org/andstatus/todoagenda/prefs/dateformat/DateFormatDialog.java

+12-8
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,10 @@ public void onResume() {
9898
// Two methods to listen for the Spinner changes
9999
@Override
100100
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
101-
if (getValue().hasPattern()) {
102-
customPatternText.setText(getValue().getPattern());
101+
if (getValue().type.hasPattern()) {
102+
customPatternText.setText(getValue().type.pattern);
103+
} else if (!getValue().hasPattern() && getValue().type.isCustomPattern()) {
104+
customPatternText.setText(DateFormatType.DEFAULT_EXAMPLE.pattern);
103105
}
104106
calcResult();
105107
}
@@ -125,7 +127,7 @@ public boolean onKey(View v, int keyCode, KeyEvent event) {
125127
@Override
126128
public void onDialogClosed(boolean positiveResult) {
127129
if (positiveResult) {
128-
DateFormatValue value = getValue();
130+
DateFormatValue value = getValue().toSave();
129131
if (preference.callChangeListener(value)) {
130132
preference.setValue(value);
131133
}
@@ -134,18 +136,20 @@ public void onDialogClosed(boolean positiveResult) {
134136

135137
private DateFormatValue getValue() {
136138
int position = typeSpinner.getSelectedItemPosition();
137-
return position >= 0
138-
? DateFormatValue.of(DateFormatType.values()[position], customPatternText.getText().toString())
139-
: DateFormatType.UNKNOWN.defaultValue();
139+
if (position >= 0) {
140+
DateFormatType selectedType = DateFormatType.values()[position];
141+
return DateFormatValue.of(selectedType, customPatternText.getText().toString());
142+
}
143+
return DateFormatType.UNKNOWN.defaultValue();
140144
}
141145

142146
private void calcResult() {
143147
DateFormatValue dateFormatValue = getValue();
144148
SimpleDateFormat sampleFormat = getSampleDateFormat();
145149
CharSequence result;
146150
try {
147-
if (customPatternText.isEnabled() != (dateFormatValue.type == DateFormatType.CUSTOM)) {
148-
customPatternText.setEnabled(dateFormatValue.type == DateFormatType.CUSTOM);
151+
if (customPatternText.isEnabled() != dateFormatValue.type.isCustomPattern()) {
152+
customPatternText.setEnabled(dateFormatValue.type.isCustomPattern());
149153
}
150154
Date sampleDate = sampleFormat.parse(sampleDateText.getText().toString());
151155
result = sampleDate == null

app/src/main/java/org/andstatus/todoagenda/prefs/dateformat/DateFormatType.java

+21-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import org.andstatus.todoagenda.R;
2525
import org.andstatus.todoagenda.util.LazyVal;
26+
import org.andstatus.todoagenda.util.StringUtil;
2627

2728
import java.util.ArrayList;
2829
import java.util.List;
@@ -39,7 +40,8 @@ public enum DateFormatType {
3940
DAY_IN_MONTH("dayInMonth", R.string.date_format_day_in_month, "dd"),
4041
MONTH_DAY("monthDay", R.string.date_format_month_day, "MM-dd"),
4142
WEEK_IN_YEAR("weekInYear", R.string.date_format_week_in_year, "ww"),
42-
PATTERN_EXAMPLE1("example1", R.string.pattern_example, "b EEE, d MMM yyyy 'W'ww"),
43+
DEFAULT_EXAMPLE("example", R.string.pattern_example, "BBB EEEE d MMM yyyy BBBB"),
44+
PATTERN_EXAMPLE1("example1", R.string.pattern_example, "b 'days,' EEE, d MMM yyyy, 'week' ww"),
4345
CUSTOM("custom-01", R.string.custom_pattern, ""),
4446
UNKNOWN("unknown", R.string.not_found, "");
4547

@@ -88,9 +90,10 @@ public static DateFormatValue unknownValue() {
8890

8991
public static List<CharSequence> getSpinnerEntryList(Context context) {
9092
List<CharSequence> list = new ArrayList<>();
93+
int exampleInd = 0;
9194
for (DateFormatType type: values()) {
9295
if (type == UNKNOWN) break;
93-
list.add(context.getText(type.titleResourceId));
96+
list.add(context.getText(type.titleResourceId) + (type.isPatternExample() ? " " + (++exampleInd) : ""));
9497
}
9598
return list;
9699
}
@@ -107,4 +110,20 @@ public int getSpinnerPosition() {
107110
}
108111
return 0;
109112
}
113+
114+
public boolean hasPattern() {
115+
return StringUtil.nonEmpty(pattern);
116+
}
117+
118+
public boolean isPatternExample() {
119+
return titleResourceId == R.string.pattern_example;
120+
}
121+
122+
public boolean isCustomPattern() {
123+
return isPatternExample() || this == CUSTOM;
124+
}
125+
126+
public DateFormatType toSave() {
127+
return isCustomPattern() ? CUSTOM : this;
128+
}
110129
}

app/src/main/java/org/andstatus/todoagenda/prefs/dateformat/DateFormatValue.java

+14-6
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222

2323
import org.andstatus.todoagenda.util.StringUtil;
2424

25-
import static org.andstatus.todoagenda.prefs.dateformat.DateFormatType.CUSTOM;
26-
2725
public class DateFormatValue {
2826
public final DateFormatType type;
2927
public final String value;
@@ -46,25 +44,35 @@ public static DateFormatValue load(String storedValue, @NonNull DateFormatValue
4644
}
4745

4846
public static DateFormatValue of(DateFormatType type, String value) {
49-
return type == CUSTOM && StringUtil.nonEmpty(value)
47+
return type.isCustomPattern() && StringUtil.nonEmpty(value)
5048
? new DateFormatValue(type, value)
5149
: type.defaultValue();
5250
}
5351

5452
@NonNull
5553
public String save() {
56-
return type == DateFormatType.UNKNOWN ? "" : type.code + ":" + value;
54+
if (type == type.toSave()) {
55+
return type == DateFormatType.UNKNOWN
56+
? ""
57+
: type.code + ":" + getPattern();
58+
} else {
59+
return toSave().save();
60+
}
5761
}
5862

5963
public boolean hasPattern() {
60-
return type == CUSTOM || StringUtil.nonEmpty(getPattern());
64+
return StringUtil.nonEmpty(getPattern());
6165
}
6266

6367
public String getPattern() {
6468
return StringUtil.isEmpty(value) ? type.pattern : value;
6569
}
6670

6771
public CharSequence getSummary(Context context) {
68-
return context.getText(type.titleResourceId) + (type == CUSTOM ? ": " + value : "");
72+
return context.getText(type.titleResourceId) + (type.isCustomPattern() ? ": " + value : "");
73+
}
74+
75+
public DateFormatValue toSave() {
76+
return DateFormatValue.of(type.toSave(), value);
6977
}
7078
}

app/src/main/java/org/andstatus/todoagenda/prefs/dateformat/DateFormatter.java

+20-10
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public CharSequence formatDate(DateTime date) {
6969
case NUMBER_OF_DAYS:
7070
return formatNumberOfDaysToEvent(context, 5, getNumberOfDaysToEvent(date));
7171
default:
72-
return "(not implemented)";
72+
return "(not implemented: " + dateFormatValue.getSummary(context) + ")";
7373
}
7474
} catch (Exception e) {
7575
return e.getLocalizedMessage();
@@ -147,25 +147,35 @@ private String formatDateCustom(DateTime date, String pattern) {
147147
}
148148

149149
private String preProcessNumberOfDaysToEvent(DateTime date, String pattern) {
150-
int ind1 = getIndexOfNumberOfDaysLetter(pattern);
151-
if (ind1 < 0) return pattern;
150+
return preProcessNumberOfDaysToEvent(date, pattern, 0, false);
151+
}
152+
153+
private String preProcessNumberOfDaysToEvent(DateTime date, String pattern, int startIndex, boolean alreadyShown) {
154+
int ind1 = getIndexOfNumberOfDaysLetter(pattern, startIndex);
155+
if (ind1 < startIndex) return pattern;
152156

153157
char patternLetter = pattern.charAt(ind1);
154158
int ind2 = ind1;
155159
while (ind2 < pattern.length() && pattern.charAt(ind2) == patternLetter) {
156160
ind2++;
157161
}
158-
CharSequence result = patternLetter == NUMBER_OF_DAYS_LOWER_LETTER
159-
? formatNumberOfDaysToEvent(context, ind2 - ind1, getNumberOfDaysToEvent(date))
160-
: formatNumberOfDaysToEventText(context, ind2 - ind1, getNumberOfDaysToEvent(date));
161-
return (ind1 > 0 ? pattern.substring(0, ind1) : "") +
162-
(result.length() == 0 ? "" : "'" + result + "'") +
162+
CharSequence numberOfDaysFormatted = alreadyShown
163+
? ""
164+
: patternLetter == NUMBER_OF_DAYS_LOWER_LETTER
165+
? formatNumberOfDaysToEvent(context, ind2 - ind1, getNumberOfDaysToEvent(date))
166+
: formatNumberOfDaysToEventText(context, ind2 - ind1, getNumberOfDaysToEvent(date));
167+
String replacement = numberOfDaysFormatted.length() == 0 ? "" : "'" + numberOfDaysFormatted + "'";
168+
String pattern2 = (ind1 > 0 ? pattern.substring(0, ind1) : "") +
169+
replacement +
163170
(ind2 < pattern.length() ? pattern.substring(ind2) : "");
171+
172+
return preProcessNumberOfDaysToEvent(date, pattern2.trim(), startIndex + replacement.length(),
173+
alreadyShown || replacement.length() > 0);
164174
}
165175

166-
private int getIndexOfNumberOfDaysLetter(String pattern) {
176+
private int getIndexOfNumberOfDaysLetter(String pattern, int startIndex) {
167177
boolean inQuotes = false;
168-
for (int ind = 0; ind < pattern.length(); ind++) {
178+
for (int ind = startIndex; ind < pattern.length(); ind++) {
169179
if ((pattern.charAt(ind) == NUMBER_OF_DAYS_LOWER_LETTER || pattern.charAt(ind) == NUMBER_OF_DAYS_UPPER_LETTER)
170180
&& !inQuotes) return ind;
171181

0 commit comments

Comments
 (0)