有什么建议可以为 Android/Java 提供一个好的库来显示时间吗?
(例如 10 分钟前、5 天前)
来自 Google I/O 2012 应用程序:
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
private static final int SECOND_MILLIS = 1000;
private static final int MINUTE_MILLIS = 60 * SECOND_MILLIS;
private static final int HOUR_MILLIS = 60 * MINUTE_MILLIS;
private static final int DAY_MILLIS = 24 * HOUR_MILLIS;
public static String getTimeAgo(long time, Context ctx) {
if (time < 1000000000000L) {
// if timestamp given in seconds, convert to millis
time *= 1000;
}
long now = getCurrentTime(ctx);
if (time > now || time <= 0) {
return null;
}
// TODO: localize
final long diff = now - time;
if (diff < MINUTE_MILLIS) {
return "just now";
} else if (diff < 2 * MINUTE_MILLIS) {
return "a minute ago";
} else if (diff < 50 * MINUTE_MILLIS) {
return diff / MINUTE_MILLIS + " minutes ago";
} else if (diff < 90 * MINUTE_MILLIS) {
return "an hour ago";
} else if (diff < 24 * HOUR_MILLIS) {
return diff / HOUR_MILLIS + " hours ago";
} else if (diff < 48 * HOUR_MILLIS) {
return "yesterday";
} else {
return diff / DAY_MILLIS + " days ago";
}
}
查看DateUtils.getRelativeTimeSpanString(),它从 API 级别 3 开始就存在了。
来自 jquery timeago 插件
这为您提供了比上述答案更多的选项和格式。
public static Date currentDate() {
Calendar calendar = Calendar.getInstance();
return calendar.getTime();
}
public static String getTimeAgo(Date date, Context ctx) {
if(date == null) {
return null;
}
long time = date.getTime();
Date curDate = currentDate();
long now = curDate.getTime();
if (time > now || time <= 0) {
return null;
}
int dim = getTimeDistanceInMinutes(time);
String timeAgo = null;
if (dim == 0) {
timeAgo = ctx.getResources().getString(R.string.date_util_term_less) + " " + ctx.getResources().getString(R.string.date_util_term_a) + " " + ctx.getResources().getString(R.string.date_util_unit_minute);
} else if (dim == 1) {
return "1 " + ctx.getResources().getString(R.string.date_util_unit_minute);
} else if (dim >= 2 && dim <= 44) {
timeAgo = dim + " " + ctx.getResources().getString(R.string.date_util_unit_minutes);
} else if (dim >= 45 && dim <= 89) {
timeAgo = ctx.getResources().getString(R.string.date_util_prefix_about) + " "+ctx.getResources().getString(R.string.date_util_term_an)+ " " + ctx.getResources().getString(R.string.date_util_unit_hour);
} else if (dim >= 90 && dim <= 1439) {
timeAgo = ctx.getResources().getString(R.string.date_util_prefix_about) + " " + (Math.round(dim / 60)) + " " + ctx.getResources().getString(R.string.date_util_unit_hours);
} else if (dim >= 1440 && dim <= 2519) {
timeAgo = "1 " + ctx.getResources().getString(R.string.date_util_unit_day);
} else if (dim >= 2520 && dim <= 43199) {
timeAgo = (Math.round(dim / 1440)) + " " + ctx.getResources().getString(R.string.date_util_unit_days);
} else if (dim >= 43200 && dim <= 86399) {
timeAgo = ctx.getResources().getString(R.string.date_util_prefix_about) + " "+ctx.getResources().getString(R.string.date_util_term_a)+ " " + ctx.getResources().getString(R.string.date_util_unit_month);
} else if (dim >= 86400 && dim <= 525599) {
timeAgo = (Math.round(dim / 43200)) + " " + ctx.getResources().getString(R.string.date_util_unit_months);
} else if (dim >= 525600 && dim <= 655199) {
timeAgo = ctx.getResources().getString(R.string.date_util_prefix_about) + " "+ctx.getResources().getString(R.string.date_util_term_a)+ " " + ctx.getResources().getString(R.string.date_util_unit_year);
} else if (dim >= 655200 && dim <= 914399) {
timeAgo = ctx.getResources().getString(R.string.date_util_prefix_over) + " "+ctx.getResources().getString(R.string.date_util_term_a)+ " " + ctx.getResources().getString(R.string.date_util_unit_year);
} else if (dim >= 914400 && dim <= 1051199) {
timeAgo = ctx.getResources().getString(R.string.date_util_prefix_almost) + " 2 " + ctx.getResources().getString(R.string.date_util_unit_years);
} else {
timeAgo = ctx.getResources().getString(R.string.date_util_prefix_about) + " " + (Math.round(dim / 525600)) + " " + ctx.getResources().getString(R.string.date_util_unit_years);
}
return timeAgo + " " + ctx.getResources().getString(R.string.date_util_suffix);
}
private static int getTimeDistanceInMinutes(long time) {
long timeDistance = currentDate().getTime() - time;
return Math.round((Math.abs(timeDistance) / 1000) / 60);
}
在您的 string.xml 文件中添加以下字符串
<!-- Date Util -->
<string name="date_util_term_less">less than</string>
<string name="date_util_term_a">a</string>
<string name="date_util_term_an">an</string>
<string name="date_util_unit_second">second</string>
<string name="date_util_unit_seconds">seconds</string>
<string name="date_util_unit_minute">minute</string>
<string name="date_util_unit_minutes">minutes</string>
<string name="date_util_unit_hour">hour</string>
<string name="date_util_unit_hours">hours</string>
<string name="date_util_unit_day">day</string>
<string name="date_util_unit_days">days</string>
<string name="date_util_unit_month">month</string>
<string name="date_util_unit_months">months</string>
<string name="date_util_unit_year">year</string>
<string name="date_util_unit_years">years</string>
<string name="date_util_prefix_lt">less than a</string>
<string name="date_util_prefix_about">about</string>
<string name="date_util_prefix_over">over</string>
<string name="date_util_prefix_almost">almost</string>
<string name="date_util_suffix">ago</string>
您可以将内置的DateUtils类与getRelative...()
方法一起使用。
您还可以使用像 libray PrettyTime 这样的 moment.js,它还为您提供翻译的内容。http://www.ocpsoft.org/prettytime/
简单的例子:
PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
//prints: “moments from now”
System.out.println(p.format(new Date(System.currentTimeMillis() + 1000*60*10)));
//prints: “10 minutes from now”
如果您需要“n 周前”和@kaderud 的答案,试试这个。
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
private static final int SECOND_MILLIS = 1000;
private static final int MINUTE_MILLIS = 60 * SECOND_MILLIS;
private static final int HOUR_MILLIS = 60 * MINUTE_MILLIS;
private static final int DAY_MILLIS = 24 * HOUR_MILLIS;
private static final int WEEK_MILLIS = 7 * DAY_MILLIS;
public static String getTimeAgo(long time) {
if (time < 1000000000000L) {
// if timestamp given in seconds, convert to millis
time *= 1000;
}
long now = System.currentTimeMillis();
if (time > now || time <= 0) {
return null;
}
// TODO: localize
final long diff = now - time;
if (diff < MINUTE_MILLIS) {
return "just now";
} else if (diff < 2 * MINUTE_MILLIS) {
return "a minute ago";
} else if (diff < 50 * MINUTE_MILLIS) {
return diff / MINUTE_MILLIS + " minutes ago";
} else if (diff < 90 * MINUTE_MILLIS) {
return "an hour ago";
} else if (diff < 24 * HOUR_MILLIS) {
return diff / HOUR_MILLIS + " hours ago";
} else if (diff < 48 * HOUR_MILLIS) {
return "yesterday";
} else if (diff < 7 * DAY_MILLIS) {
return diff / DAY_MILLIS + " days ago";
} else if (diff < 2 * WEEK_MILLIS) {
return "a week ago";
} else {
return diff / WEEK_MILLIS + " weeks ago";
}
}
你可以试试我的库Time4A,它是 Time4J 的 Android 版本。演示:
Locale uk = Locale.UK;
TZID paris = EUROPE.PARIS;
ChronoFormatter<Moment> f =
ChronoFormatter.ofMomentPattern("d. MMMM uuuu h:mm B", PatternType.CLDR, uk, paris);
PrettyTime pt = PrettyTime.of(uk);
// => examples for relative formats
Moment moment = f.parse("4. January 2016 5:45 in the afternoon");
System.out.println(pt.printRelative(moment, paris));
// output: 1 week ago
Moment now = SystemClock.currentMoment();
System.out.println(pt.printRelative(now, paris));
// output: now
Moment shortTimeAgo = now.minus(15, SI.SECONDS);
System.out.println(pt.printRelative(shortTimeAgo, paris));
// output: 15 seconds ago
TimeUnit precision = TimeUnit.DAYS;
System.out.println(pt.printRelative(shortTimeAgo, Timezone.of(paris), precision));
// output: today
// => examples for list formats
Duration<?> duration = // this way for getting duration requires extra range-module
MomentInterval.between(moment, now).getNominalDuration(
Timezone.of(paris),
DAYS, HOURS, MINUTES);
System.out.println(pt.print(duration));
// output: 11 days, 1 hour and 26 minutes
System.out.println(pt.print(duration, TextWidth.ABBREVIATED));
// output: 11 days, 1 hr, 26 min
实际上支持72 种语言(v3.18-2016c),包括本地化复数规则(对奴隶语言或阿拉伯语很重要)和三种不同的文本宽度:
af am ar az be bg bn bs ca cs da de el en es et fa fi
fil fr ga gu he hi hr hu hy id is it ja ka kk km kn ko
ky lo lt lv mk mn mr ms my nb ne nl nn pa pl pt ro ru
si sk sl sq sr sv sw ta te th tk tr uk ur uz vi zh zu
支持从年到秒的所有单位(甚至列表格式的毫秒、微米、纳米)。
为了java.util.Date
从/到 time4j 类型转换或长时间戳(表示自 Unix 纪元以来的毫秒数),您可以使用:
java.util.Date d = TemporalType.JAVA_UTIL_DATE.from(moment);
long epochMillis = TemporalType.MILLIS_SINCE_UNIX.from(moment);
Moment m1 = TemporalType.JAVA_UTIL_DATE.translate(d);
Moment m2 = TemporalType.MILLIS_SINCE_UNIX.translate(epochMillis);
2019-06-06 更新:
具有 gradle-dependency 的较新版本 Time4A-4.4-2019a
dependencies {
implementation group: 'net.time4j', name: 'time4j-android', version: '4.4-2019a'
}
支持94 种语言,现在还包括“下周日”等相关模式。
我检查了这篇文章中提到的所有答案,但无法从任何答案中获得正确且格式化的输出。终于找到了我在这篇文章中寻找的答案, http: //memorynotfound.com/calculate-relative-time-time-ago-java/
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class TimeAgo {
public static final Map<String, Long> times = new LinkedHashMap<>();
static {
times.put("year", TimeUnit.DAYS.toMillis(365));
times.put("month", TimeUnit.DAYS.toMillis(30));
times.put("week", TimeUnit.DAYS.toMillis(7));
times.put("day", TimeUnit.DAYS.toMillis(1));
times.put("hour", TimeUnit.HOURS.toMillis(1));
times.put("minute", TimeUnit.MINUTES.toMillis(1));
times.put("second", TimeUnit.SECONDS.toMillis(1));
}
public static String toRelative(long duration, int maxLevel) {
StringBuilder res = new StringBuilder();
int level = 0;
for (Map.Entry<String, Long> time : times.entrySet()){
long timeDelta = duration / time.getValue();
if (timeDelta > 0){
res.append(timeDelta)
.append(" ")
.append(time.getKey())
.append(timeDelta > 1 ? "s" : "")
.append(", ");
duration -= time.getValue() * timeDelta;
level++;
}
if (level == maxLevel){
break;
}
}
if ("".equals(res.toString())) {
return "0 seconds ago";
} else {
res.setLength(res.length() - 2);
res.append(" ago");
return res.toString();
}
}
public static String toRelative(long duration) {
return toRelative(duration, times.size());
}
public static String toRelative(Date start, Date end){
assert start.after(end);
return toRelative(end.getTime() - start.getTime());
}
public static String toRelative(Date start, Date end, int level){
assert start.after(end);
return toRelative(end.getTime() - start.getTime(), level);
}
}
您可以使用 android-ago 模块https://github.com/curioustechizen/android-ago
在您的 XML 中添加组件
<com.github.curioustechizen.ago.RelativeTimeTextView
android:id="@+id/timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:relative_time_prefix="Completed "
android:layout_marginTop="@dimen/margin_primary" />
设置时间参考视图代码
RelativeTimeTextView v = (RelativeTimeTextView)findViewById(R.id.timestamp); //Or just use Butterknife!
v.setReferenceTime(new Date().getTime());
只需输入时间戳编号并获得您的问题的答案。输出根据您的位置来。
public static String getTimeAgo(long timestamp) {
Calendar cal = Calendar.getInstance();
TimeZone tz = cal.getTimeZone();//get your local time zone.
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm a");
sdf.setTimeZone(tz);//set time zone.
String localTime = sdf.format(new Date(timestamp * 1000));
Date date = new Date();
try {
date = sdf.parse(localTime);//get local date
} catch (ParseException e) {
e.printStackTrace();
}
if(date == null) {
return null;
}
long time = date.getTime();
Date curDate = currentDate();
long now = curDate.getTime();
if (time > now || time <= 0) {
return null;
}
int timeDIM = getTimeDistanceInMinutes(time);
String timeAgo = null;
if (timeDIM == 0) {
timeAgo = "less than a minute";
} else if (timeDIM == 1) {
return "1 minute";
} else if (timeDIM >= 2 && timeDIM <= 44) {
timeAgo = timeDIM + " minutes";
} else if (timeDIM >= 45 && timeDIM <= 89) {
timeAgo = "about an hour";
} else if (timeDIM >= 90 && timeDIM <= 1439) {
timeAgo = "about " + (Math.round(timeDIM / 60)) + " hours";
} else if (timeDIM >= 1440 && timeDIM <= 2519) {
timeAgo = "1 day";
} else if (timeDIM >= 2520 && timeDIM <= 43199) {
timeAgo = (Math.round(timeDIM / 1440)) + " days";
} else if (timeDIM >= 43200 && timeDIM <= 86399) {
timeAgo = "about a month";
} else if (timeDIM >= 86400 && timeDIM <= 525599) {
timeAgo = (Math.round(timeDIM / 43200)) + " months";
} else if (timeDIM >= 525600 && timeDIM <= 655199) {
timeAgo = "about a year";
} else if (timeDIM >= 655200 && timeDIM <= 914399) {
timeAgo = "over a year";
} else if (timeDIM >= 914400 && timeDIM <= 1051199) {
timeAgo = "almost 2 years";
} else {
timeAgo = "about " + (Math.round(timeDIM / 525600)) + " years";
}
return timeAgo + " ago";
}
public static Date currentDate() {
Calendar calendar = Calendar.getInstance();
return calendar.getTime();
}
private static int getTimeDistanceInMinutes(long time) {
long timeDistance = currentDate().getTime() - time;
return Math.round((Math.abs(timeDistance) / 1000) / 60);
}