我正在审核Google I/O Session 2012 app并遇到了这个TODO
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";
}
}
这让我想知道本地化的步骤是什么。
答案 0 :(得分:19)
如果您不需要自定义字符串,您还可以使用DateUtils.getRelativeTimeSpanString,它会产生以下字符串:
样本用法:
final CharSequence relativeTimeSpan = DateUtils.getRelativeTimeSpanString(time, now, 0);
答案 1 :(得分:9)
来自Ian Lake的回答:
final CharSequence relativeTimeSpan = DateUtils.getRelativeTimeSpanString(time, now, 0);
DateUtils.getRelativeTimeSpanString产生如下内容:
或者,这将允许使用给定的res
通过Android Context
框架提供翻译,如果您从框架方法中获得所需的消息传递差异,则非常有用。
public static String getTimeAgo(long time, Context context) {
if (time < 1000000000000L)
// if timestamp given in seconds, convert to millis
time *= 1000;
final long now = getCurrentTime(context);
if (time > now || time <= 0) return "";
final Resources res = context.getResources();
final long time_difference = now - time;
if (time_difference < _A_MINUTE)
return res.getString(R.string.just_now);
else if (time_difference < 50 * _A_MINUTE)
return res.getString(R.string.time_ago,
res.getQuantityString(R.plurals.minutes, (int) time_difference / _A_MINUTE, time_difference / _A_MINUTE));
else if (time_difference < 24 * _AN_HOUR)
return res.getString(R.string.time_ago,
res.getQuantityString(R.plurals.hours, (int) time_difference / _AN_HOUR, time_difference / _AN_HOUR));
else if (time_difference < 48 * _AN_HOUR)
return res.getString(R.string.yesterday);
else
return res.getString(R.string.time_ago,
res.getQuantityString(R.plurals.days, (int) time_difference / _A_DAY, time_difference / _A_DAY));
}
我将常量定义为:
/** One second (in milliseconds) */
private static final int _A_SECOND = 1000;
/** One minute (in milliseconds) */
private static final int _A_MINUTE = 60 * _A_SECOND;
/** One hour (in milliseconds) */
private static final int _AN_HOUR = 60 * _A_MINUTE;
/** One day (in milliseconds) */
private static final int _A_DAY = 24 * _AN_HOUR;
然后剩下的工作是复数和字符串资源的结构。
我的默认本地是en,所以res/values/strings.xml
:
<!-- time ago strings -->
<string name="just_now">just now</string>
<string name="time_ago">%s ago</string>
<string name="yesterday">yesterday</string>
然后res/values/plurals.xml
:
<plurals name="minutes">
<item quantity="one">a minute</item>
<item quantity="other">%d minutes</item>
</plurals>
<plurals name="hours">
<item quantity="one">an hour</item>
<item quantity="other">%d hours</item>
</plurals>
<plurals name="days">
<item quantity="one">a day</item>
<item quantity="other">%d days</item>
</plurals>
这种方法应该允许你定位语言的词汇和语法,因为不同的语言不仅对于像“分钟”这样的单词有不同的单词,而且它们对于如何根据数量复数单词也有不同的规则。因此,复数资源利用Android框架支持多元化本地化。剩下的就是提供翻译。
答案 2 :(得分:1)
这个答案类似于丹德尔的回答,除了:
首先,让我们编写返回格式化日期的主函数:
public String getStringFormattedDate(Context context, Date postDate){
Calendar postCalendar = Calendar.getInstance();
postCalendar.setTime(postDate);
Calendar currentCalendar = Calendar.getInstance();
long delta = Math.abs(currentCalendar.getTimeInMillis() - postCalendar .getTimeInMillis()) / 1000;
//**yesterday**
//This has to be checked first, otherwise, yesterday logic
//will be overridden by "seconds ago", "minutes ago", "hours ago"
if(isYesterday(postCalendar , currentCalendar)){
return context.getResources().getString(R.string.yesterday);
}
//seconds ago
else if (delta < 60)
{
return context.getResources().getQuantityString(R.plurals.seconds, (int)delta, (int)delta);
}
//minutes ago
else if (delta < 3600) // 60 * 60
{
delta /= 60.0; // convert seconds to minutes
return context.getResources().getQuantityString(R.plurals.minutes, (int)delta, (int)delta);
}
//hours ago
else if (delta < 86400) // 24 * 60 * 60
{
delta /= (60.0*60.0); // convert seconds to hours
return context.getResources().getQuantityString(R.plurals.hours, (int)delta, (int)delta);
}
//older dates
else{
delta /= (60.0*60.0*24.0); // convert seconds to days
return context.getResources().getString(R.string.time_ago, context.getResources().getQuantityString(R.plurals.days, (int) delta , (int) delta));
}
}
函数isYesterday()
,用于检查postCalendar昨天是否与当前日历进行比较:
//return true, if postCalendar is a day behind currentCalendar
private boolean isYesterday(Calendar postCalendar, Calendar currentCalendar){
Calendar cloneCurrentCalendar = (Calendar) currentCalendar.clone();
resetTime(cloneCurrentCalendar);
Calendar clonePostCalendar = (Calendar) postCalendar.clone();
resetTime(clonePostCalendar);
clonePostCalendar.add(Calendar.DAY_OF_MONTH, 1);
return (cloneCurrentCalendar.compareTo(clonePostCalendar) == 0);
}
重置日历实例的函数resetTime()
,仅用于比较日历日期:
//set Time to 00:00:00
private void resetTime(Calendar calendar){
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
}
答案 3 :(得分:0)
我在答案中略微编辑了代码。我得到了#0; 0小时前&#34;字符串,由long和int的划分引起的。此外,答案中缺少private static Class<Math> Math;
for (PropertyDescriptor propertyDescriptor
: Introspector.getBeanInfo(Math).getPropertyDescriptors()) {
System.out.println(propertyDescriptor.getReadMethod());
}
方法,因此我使用getCurrentTime()
。这是我的修改,它解决了System.getCurrentTimeInMillis()
问题。
0 hour ago
public static String getTimeAgo(long time, Context context) {
if (time < 1000000000000L) {
// if timestamp given in seconds, convert to millis
time *= 1000;
}
final long now = System.currentTimeMillis();
if (time > now || time <= 0) return "";
final Resources res = context.getResources();
final long time_difference = now - time;
if (time_difference < C._A_MINUTE)
return res.getString(R.string.just_now);
else if (time_difference < 50 * C._A_MINUTE)
return res.getString(R.string.time_ago,
res.getQuantityString(R.plurals.minutes, (int) time_difference / C._A_MINUTE, time_difference / C._A_MINUTE));
else if (time_difference < 24 * C._AN_HOUR)
return res.getString(R.string.time_ago,
res.getQuantityString(R.plurals.hours, (int) Math.ceil((double)time_difference / C._AN_HOUR), time_difference / C._AN_HOUR));
else if (time_difference < 48 * C._AN_HOUR)
return res.getString(R.string.yesterday);
else
return res.getString(R.string.time_ago,
res.getQuantityString(R.plurals.days, (int) Math.ceil((double)time_difference / C._A_DAY), time_difference / C._A_DAY));
}
是我保持常量的地方。这是:
C.java
其他文件(public class C {
/** One second (in milliseconds) */
public static final int _A_SECOND = 1000;
/** One minute (in milliseconds) */
public static final int _A_MINUTE = 60 * _A_SECOND;
/** One hour (in milliseconds) */
public static final int _AN_HOUR = 60 * _A_MINUTE;
/** One day (in milliseconds) */
public static final int _A_DAY = 24 * _AN_HOUR;
和plurals.xml
)相同。请参阅上面的答案。