前言
根据城市获取当前城市所在时区的当前时间,在一些业务场景上是刚需的要求。 比如到其他时区下单,查询商品,或者我们要去预订当地的酒店,等等场景,都需要获取当前城市的当前时间。
问题: 世界上N多个城市,大概3W多个,如何批量去获取,在不能确保网上copy的能准确的情况下,身为程序猿的我们,不能没有招。
方法
用Java的LocalDateTime
ZoneId zoneId = ZoneId.of(timeZoneId);
LocalDateTime now = LocalDateTime.now(zoneId);
那么问题来了,timeZoneId(时区ID) 哪里来,这个就不能确保网上的都对了,万一错误,我们的逻辑就取不到正确的时间。
如上图的第三列
有了这个时区ID,我们才能通过LocalDateTime去获取当前时间。
获取时区ID
百度api
通过经纬度,获取所在城市的时区ID
百度的有个限制,如果个人的,每天最多300个,一个key的话。如果要加就申请下,应该还是能加点量的。
private static String getBaiduTimeZone(BigInteger cityId, String latitude, String longitude){
//http://api.map.baidu.com/timezone/v1?coord_type=wgs84ll&location=-36.52,174.46×tamp=1473130354&ak=你的ak //GET请求
try {
log.debug("System.currentTimeMillis() ={} ",System.currentTimeMillis() / 1000);
String url = "http://api.map.baidu.com/timezone/v1";
Map<String, Object> params = new HashMap<>();
params.put("location",latitude+","+longitude);
params.put("timestamp",System.currentTimeMillis() / 1000);
params.put("ak","youBaiduKey");
HttpRequest httpRequest = HttpRequest.get(url).form(params).timeout(60000);
String result = httpRequest.execute().body();
JsonNode jsonNode = JsonUtil.readTree(result);
String timezone_id = jsonNode.get("timezone_id")!=null? jsonNode.get("timezone_id").toString():null;
if(timezone_id == null){
return null;
}
return timezone_id.replaceAll(""","");
}catch (Exception e){
log.error(e.getMessage());
}
return null;
}
Google地图的获取时区ID
谷歌地图的是要收费的, 但有 免费用一个月200$
获取时区代码如下:
public String getTimeZone(LatAndLonDTO latAndLon) {
try{
LatLng location = new LatLng(new BigDecimal(latAndLon.getLatitude()).doubleValue(), new BigDecimal(latAndLon.getLongitude()).doubleValue());
PendingResult<TimeZone> timeZoneInfo = TimeZoneApi.getTimeZone(GoogleApiContext.getInstance(), location);
if(timeZoneInfo != null) {
return timeZoneInfo.await().getID();
}
} catch(Exception e) {
//log info some message
throw new Exception(e);
}
return null;
}
Python的时区库
Python的时区库 ,可以大批量的获取,重点是免费哈。但会有个别的解析不了。
通过时区ID获取时区的当前时间
最后就是获取时区的时间了
/**
* 通过时区ID获取当前时区的当前时间戳
*/
private Long getTimestampByTimeZoneId(String timeZoneId){
if(timeZoneId == null){
return LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
}
try {
ZoneId zoneId = ZoneId.of(timeZoneId);
LocalDateTime now = LocalDateTime.now(zoneId);
return now.toInstant(ZoneOffset.of("+8")).toEpochMilli();
}catch (Exception e){
log.error("getTimeByTimeZoneId error !! timeZoneId={} ,and Exception = {}",timeZoneId,e.getMessage());
}
return LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
}
总结
获取时区ID获取要存下来,不要每次都去获取时区ID。
1、落库存储
2、存到缓存,方便快速使用