场景说明: 我们在给客户端输出 api 的时候, 他们需要我们给他们输出时间戳的格式为 "几小时前", "几分钟前" 类似的格式.
而我们的 JavaBean 对象里面的时间戳字段都是 int 或者 long , 如果直接转成字符串, 需要在 bean 类里面加一个字段来标识, 而且和原本的时间戳字段重复冗余. 抛开这不说,每次遇到时间戳的时候都要调用一个友好时间戳转换方法,代码也不好维护. 所以我们一般都是在 api 出口同一来过滤转换这个时间戳. 之前在我大 PHP 里面,我们是使用array_walk_recursive来递归处理输出的数组. 然后处理完数组之后再将其json_encode.
array_walk_recursive($rtnArr, array('BaseMobileApi', 'tsToItime'));
class BaseMobileApi{
public static function tsToItime(&$value, $key)
{
if ($key == 'ts') {
$value = GlobalClass::itime($value);
$value = $value . "前";
}
if ($key == 'last_ts') {
$value = GlobalClass::itime($value);
$value = $value . "前更新";
}
}
}
所以这一次, 我也在想怎么去遍历JSONObject,想到自己实现一个递归, 然后还要判断这个JSONObject里面是否会有List等结构. 在尝试递归修改 JSONObject 里面的子JSONObject里面key对应的值的时候, 遇到了问题.问了下好友@明明, 他告诉我可以用getJSONObject方法,是引用修改, 同时他建议我是否可以尝试用正则呢? 是呀, 已经是字符串了,直接正则不就行啦.也不用考虑 json 字符串的格式了,也不用递归了.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by zhoumengkang on 2/6/15.
*/
public class OutputFilter {
public static String tsFilter(String str){
String patternString = "\"ts\":(\\d+)";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(str);
StringBuffer sb = new StringBuffer();
while(matcher.find()) {
matcher.appendReplacement(sb, "\"ts\":\"" + ts2Str(Integer.parseInt(matcher.group(1))) + "\"");
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 时间戳友好转换
* @param ts
* @return
*/
public static String ts2Str(int ts){
int now = (int) (System.currentTimeMillis()/1000);
int offset = now - ts;
if(offset < 1){
return "1秒前";
}else if(offset < 60){
return offset + "秒前";
}else if(offset < 3600){
int minutes = offset/60;
return minutes + "分钟前";
}else if(offset < 86400){
int hours = offset/3600;
return hours + "小时前";
}else if(offset < 2592000){
int days = offset/86400;
return days + "天前";
}else if(offset <= 7776000){
int months = offset/2592000;
return months + "个月前";
}else{
return "3个月前";
}
}
public static String ts2Str(long ts){
int tsNew = (int) (ts/1000);
return ts2Str(tsNew);
}
}