Welcome to MLink Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
340 views
in Technique[技术] by (71.8m points)

根据传入的float型数字获取不同时区的当地时间? java

请问有优雅的实现吗?

项目中遇到一个问题.要求根据传入的数字(浮点型)获取不同时区 当前的时间

范围-11->12 从西至东 总共二十四个时区 考虑到部分地区(如印度 当地是 东 +6.5 时区) 所以要求可以输入小数.

目前代码如下:

public static String getFormatedDateString(float timeZoneOffset){
        if (timeZoneOffset > 13 || timeZoneOffset < -12) {
            timeZoneOffset = 0;
        }

        //获取整数部分
        int zNum=(int)timeZoneOffset;
        //获取小数部分
        float fNum=timeZoneOffset%1;
        int newTime=(int)(timeZoneOffset * 60 * 60 * 1000);
        TimeZone timeZone;
        String[] ids = TimeZone.getAvailableIDs(zNum);
        if (ids.length == 0) {
            timeZone = TimeZone.getDefault();
        } else {
            timeZone = new SimpleTimeZone(newTime, ids[0]);
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(timeZone);
        //加上偏移后的时间戳
      Long n=  new Date().getTime()+(int)(fNum*60*60*1000);
        return  sdf.format(new Date(n));
    }

请各位大佬 优化一下 昨天跑sai没过


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

现在我看到DateSimpleDateFormat心理就是慌的,哈哈哈,不过能写出来用这个也行。但你也提到你自己没跑过,一般来说,时区,时间之类的,用Java8新的时间API处理起来相对而言要简单一些吧。

一般过程是这样:
Java8的时间API中,偏移量表示时区的是ZoneOffset,一般根据偏移的小时来初始化的,例如

ZoneOffset zoneOffset = ZoneOffset.ofHours(5);
ZoneOffset zoneOffset1 = ZoneOffset.ofHours(-5);

因为这已经是时区偏移量了,然后用上面的zoneOffset结合专门表示偏移量时间的类OffsetDateTime就可以获取到当前在该时区偏移量的偏移量时间

OffsetDateTime offsetDateTime = OffsetDateTime.now(zoneOffset)  

OffsetDateTimetoString()方法就可以看出来,后面是带有偏移量

2020-08-23T05:43:40.018-05:00

Java8中表示本地时间的是LocalDateTime,我们用OffsetDateTime是可以直接转换成LocalDateTime

LocalDateTime localDateTime = offsetDateTime.toLocalDateTime();

然后根据LocalDateTime就可以格式化成你想要的样子

String formatLocalDateTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

所以只要我们可以拿到ZoneOffset,其实后面的代码是水到渠成的,奈何题主提到前面的小时是一个float,那这需要我们把float中不足一小时的提取出来,然后换一个方式来初始化ZoneOffset,也就是ZoneOffsetof(String offsetId)方法,在其方法注释中我们就可以看到,它支持时分秒字符串传入的,因此我们只需要把题主的参数timeZoneOffset转换成时分秒即可

image.png

而在Java8中,时间API里表示时分秒的类是LocalTime,该类的静态方法ofSecondOfDay是可以根据一天之内的秒数初始化的,因此我们只需要把timeZoneOffset转换成秒,然后初始化成LocalTime即可,而LocalTimetoString方法恰好就是hh:mm:ss,我们只要之前把参数timeZoneOffset的符号保留下来即可,因此完整代码如下:

public static String getFormatedDateString(float timeZoneOffset){
        String prefix = "+";
        if (timeZoneOffset < 0) {
            prefix = "-";
            timeZoneOffset = 0 - timeZoneOffset;
        }
        long seconds = (long) (ChronoUnit.HOURS.getDuration().getSeconds() * timeZoneOffset);
        ZoneOffset zoneOffset = ZoneOffset.of(prefix + LocalTime.ofSecondOfDay(seconds).toString());
        String formatLocalDateTime = OffsetDateTime.now(zoneOffset)
                                                   .toLocalDateTime()
                                                   .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        return formatLocalDateTime;
    }

当然其中DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")可以在外面写成final static可能更好,毕竟是一个常量般存在,不必每次初始化一个DateTimeFormatter

试试看看达到题主的效果没,如果没有达到,当我打脸,哈哈哈哈,不过还是要告诉我,我好做哈修改!Σ(っ °Д °;)っ


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to MLink Developer Q&A Community for programmer and developer-Open, Learning and Share
...