Browse Source

Relative time improvements

widgets
Ezerous 5 years ago
parent
commit
160d77c870
  1. 2
      app/build.gradle
  2. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  3. 51
      app/src/main/java/gr/thmmy/mthmmy/utils/DateTimeUtils.java
  4. 19
      app/src/main/java/gr/thmmy/mthmmy/utils/RelativeTimeTextView.java
  5. 106
      app/src/test/java/gr/thmmy/mthmmy/utils/DateTimeUtilsTest.java
  6. 2
      app/src/test/java/gr/thmmy/mthmmy/utils/parsing/ThmmyDateTimeParserTest.java

2
app/build.gradle

@ -78,7 +78,7 @@ dependencies {
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-alpha04' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-alpha05'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.exifinterface:exifinterface:1.1.0-beta01' implementation 'androidx.exifinterface:exifinterface:1.1.0-beta01'
implementation 'com.google.android.material:material:1.0.0' implementation 'com.google.android.material:material:1.0.0'

1
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java

@ -5,7 +5,6 @@ import android.app.NotificationManager;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Rect; import android.graphics.Rect;

51
app/src/main/java/gr/thmmy/mthmmy/utils/DateTimeUtils.java

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.utils; package gr.thmmy.mthmmy.utils;
import androidx.annotation.VisibleForTesting;
import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@ -20,38 +22,55 @@ public class DateTimeUtils {
return dateTime; return dateTime;
} }
private static final long MONTH_IN_MILLIS = DAY_IN_MILLIS*30; private static final long MONTH_IN_MILLIS = 30*DAY_IN_MILLIS;
private static final long DECADE_IN_MILLIS = YEAR_IN_MILLIS*10; private static final long DECADE_IN_MILLIS = 10*YEAR_IN_MILLIS;
@VisibleForTesting
static String getRelativeTimeSpanString(long time) {
long now = System.currentTimeMillis();
static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution) {
boolean past = (now >= time); boolean past = (now >= time);
long duration = Math.abs(now - time); long duration = Math.abs(now - time);
String format; String format;
long count; long count, mod;
if (duration < MINUTE_IN_MILLIS && minResolution < MINUTE_IN_MILLIS) { if(duration < 45*SECOND_IN_MILLIS)
count = duration / SECOND_IN_MILLIS; return "just now";
format = "%d sec"; else if (duration < 45*MINUTE_IN_MILLIS) {
} else if (duration < HOUR_IN_MILLIS && minResolution < HOUR_IN_MILLIS) {
count = duration/MINUTE_IN_MILLIS; count = duration/MINUTE_IN_MILLIS;
format = "%d min"; mod = duration % MINUTE_IN_MILLIS;
} else if (duration < DAY_IN_MILLIS && minResolution < DAY_IN_MILLIS) { if(mod >= 30*SECOND_IN_MILLIS)
count += 1;
format = "%dm";
} else if (duration < 22*HOUR_IN_MILLIS) {
count = duration/HOUR_IN_MILLIS; count = duration/HOUR_IN_MILLIS;
format = "%d hour"; format = "%dh";
if(count>1) mod = (duration%HOUR_IN_MILLIS)/MINUTE_IN_MILLIS;
format = format + 's'; if(count<4 && mod>10 && mod<50)
} else if (duration < MONTH_IN_MILLIS && minResolution < MONTH_IN_MILLIS) { format = format + mod +"m";
else if(mod >= 30)
count += 1;
} else if (duration < 26*DAY_IN_MILLIS) {
count = duration/DAY_IN_MILLIS; count = duration/DAY_IN_MILLIS;
format = "%d day"; format = "%d day";
mod = duration % DAY_IN_MILLIS;
if(mod >= 12*HOUR_IN_MILLIS)
count += 1;
if(count>1) if(count>1)
format = format + 's'; format = format + 's';
} else if (duration < YEAR_IN_MILLIS && minResolution < YEAR_IN_MILLIS) { } else if (duration < 320*DAY_IN_MILLIS) {
count = duration/MONTH_IN_MILLIS; count = duration/MONTH_IN_MILLIS;
format = "%d month"; format = "%d month";
mod = duration % MONTH_IN_MILLIS;
if(mod >= 15*DAY_IN_MILLIS)
count += 1;
if(count>1) if(count>1)
format = format + 's'; format = format + 's';
} else if (duration < DECADE_IN_MILLIS && minResolution < DECADE_IN_MILLIS) { } else if (duration < DECADE_IN_MILLIS) {
count = duration/YEAR_IN_MILLIS; count = duration/YEAR_IN_MILLIS;
format = "%d year"; format = "%d year";
mod = duration % YEAR_IN_MILLIS;
if(mod >= 183*DAY_IN_MILLIS)
count += 1;
if(count>1) if(count>1)
format = format + 's'; format = format + 's';
} }

19
app/src/main/java/gr/thmmy/mthmmy/utils/RelativeTimeTextView.java

@ -100,24 +100,7 @@ public class RelativeTimeTextView extends TextView {
*/ */
if (this.mReferenceTime == -1L) if (this.mReferenceTime == -1L)
return; return;
setText(getRelativeTimeDisplayString(mReferenceTime, System.currentTimeMillis())); setText(getRelativeTimeSpanString(mReferenceTime));
}
/**
* Get the text to display for relative time.
* <br/>
* @param referenceTime The reference time passed in through {@link #setReferenceTime(long)} or through {@code reference_time} attribute
* @param now The current time
* @return The display text for the relative time
*/
protected CharSequence getRelativeTimeDisplayString(long referenceTime, long now) {
long difference = now - referenceTime;
return (difference >= 0 && difference<=DateUtils.MINUTE_IN_MILLIS) ?
"just now" :
getRelativeTimeSpanString(
mReferenceTime,
now,
DateUtils.MINUTE_IN_MILLIS);
} }
@Override @Override

106
app/src/test/java/gr/thmmy/mthmmy/utils/DateTimeUtilsTest.java

@ -0,0 +1,106 @@
package gr.thmmy.mthmmy.utils;
import net.lachlanmckee.timberjunit.TimberTestRule;
import org.joda.time.DateTime;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static gr.thmmy.mthmmy.utils.DateTimeUtils.getRelativeTimeSpanString;
import static org.junit.Assert.assertArrayEquals;
import static org.mockito.Mockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest(DateTimeUtils.class)
public class DateTimeUtilsTest {
@Rule
public TimberTestRule logAllAlwaysRule = TimberTestRule.logAllAlways();
private final long NOW = System.currentTimeMillis();
private final String [] expectedRelativeTimeSpans = {
"just now",
"just now",
"just now",
"1m",
"1m",
"1m",
"2m",
"3m",
"1h",
"1h15m",
"2h",
"3h20m",
"4h",
"20h",
"21h",
"21h",
"21h",
"22h",
"1 day",
"1 day",
"2 days",
"2 days",
"3 days",
"16 days",
"1 month",
"2 months",
"1 year",
"1 year",
"2 years",
"a long time ago"
};
private final long [] times = {
NOW,
newDT().minusSeconds(44).getMillis(),
newDT().minusSeconds(44).minusMillis(500).getMillis(),
newDT().minusSeconds(45).getMillis(),
newDT().minusSeconds(89).getMillis(),
newDT().minusSeconds(89).minusMillis(500).getMillis(),
newDT().minusSeconds(90).getMillis(),
newDT().minusMinutes(3).minusSeconds(10).getMillis(),
newDT().minusHours(1).minusMinutes(4).getMillis(),
newDT().minusHours(1).minusMinutes(15).getMillis(),
newDT().minusHours(2).minusMinutes(4).getMillis(),
newDT().minusHours(3).minusMinutes(20).getMillis(),
newDT().minusHours(3).minusMinutes(51).getMillis(),
newDT().minusHours(20).minusMinutes(10).getMillis(),
newDT().minusHours(20).minusMinutes(30).getMillis(),
newDT().minusHours(21).getMillis(),
newDT().minusHours(21).minusMinutes(29).getMillis(),
newDT().minusHours(21).minusMinutes(30).getMillis(),
newDT().minusHours(22).minusMinutes(30).getMillis(),
newDT().minusHours(34).getMillis(),
newDT().minusHours(38).getMillis(),
newDT().minusDays(2).minusHours(10).getMillis(),
newDT().minusDays(2).minusHours(17).getMillis(),
newDT().minusDays(16).getMillis(),
newDT().minusDays(30+12).getMillis(),
newDT().minusDays(2*30+14).getMillis(),
newDT().minusDays(14*30).getMillis(),
newDT().minusMonths(15).getMillis(),
newDT().minusMonths(22).getMillis(),
newDT().minusYears(22).getMillis()
};
private DateTime newDT(){
return new DateTime(NOW);
}
@Test
public void relativeTimeSpansAreConvertedCorrectly() {
PowerMockito.mockStatic(System.class);
when(System.currentTimeMillis()).thenReturn(NOW);
String[] timeStrings = new String[times.length];
for(int i=0; i<times.length; i++)
timeStrings[i] = getRelativeTimeSpanString(times[i]);
assertArrayEquals(expectedRelativeTimeSpans,timeStrings);
}
}

2
app/src/test/java/gr/thmmy/mthmmy/utils/parsing/ThmmyDateTimeParserTest.java

@ -75,7 +75,7 @@ public class ThmmyDateTimeParserTest {
}; };
@Test @Test
public void todayDateTimeDontConvertToNull() { public void todayDateTimeConvertToNonNull() {
stub(method(ThmmyDateTimeParser.class, GET_DTZ)).toReturn(DateTimeZone.forID(TIME_ZONE)); stub(method(ThmmyDateTimeParser.class, GET_DTZ)).toReturn(DateTimeZone.forID(TIME_ZONE));
for (String todayDateTime : todayDateTimes) for (String todayDateTime : todayDateTimes)

Loading…
Cancel
Save