String.format,long和DateTime转换

问题描述 投票:0回答:1

如果这个问题是重复的,我很抱歉,我通过Google没有找到任何东西。

对于我的问题。

我有以下测试:

public void testSecondsToMinutes() {
    long zero = 0;
    long thirty_seconds = 30;
    long one_minute = 60;
    long thirty_minutes_fiftynine_seonds = 1859;
    long two_hours_ten_miutes_fourty_seconds = 7840;

    String format1 = "00:00:00";
    String format2 = "00:00:30";
    String format3 = "00:01:00";
    String format4 = "00:30:59";
    String format5 = "02:10:40";

    assertEquals(format1,Entrypoint.secondsToMinutes(zero));
    assertEquals(format2,Entrypoint.secondsToMinutes(thirty_seconds));
    assertEquals(format3,Entrypoint.secondsToMinutes(one_minute));
    assertEquals(format4,Entrypoint.secondsToMinutes(thirty_minutes_fiftynine_seonds));
    assertEquals(format5,Entrypoint.secondsToMinutes(two_hours_ten_miutes_fourty_seconds)); 
}

和下面的函数。

public static String secondsToMinutes(long seconds)
{
    return String.format("%TH:%TM:%TS", seconds, seconds, seconds);
}

在Java文档中 格式化 说明如下。

The following conversion characters are used for formatting common date/time compositions.
This conversion may be applied to long, Long, Calendar, and Date.
[...]
'R' '\u0052'    Time formatted for the 24-hour clock as "%tH:%tM"
'T' '\u0054'    Time formatted for the 24-hour clock as "%tH:%tM:%tS".

然而,我得到了以下的比较失败。

expected 00:00:00 but was 01:00:00

我一定是漏掉了什么明显的东西... I must be missing something obvious here...

java string formatter
1个回答
2
投票

当你传递一个 longString.format它被解释为从纪元开始的毫秒,这与你打算从午夜开始的秒数是完全不同的实体。

你的问题最容易通过直接编码你的意图来解决。

public static String secondsToTwentyFourHourString(long seconds) {
    return String.format("%1$TH:%1$TM:%1$TS", LocalTime.ofSecondOfDay(seconds));
}

这样一来,你就可以指定一个不依赖于时区的操作。

同样的逻辑也适用于 DateTimeFormatter:

public static String secondsToTwentyFourHourString(long seconds) {
    return LocalTime.ofSecondOfDay(seconds)
        .format(DateTimeFormatter.ofPattern("HH:mm:ss"));
}

2
投票

所以,为了回答这个问题。

我其实已经尝试了本地的 strftime 在C语言中。

#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char*argv[])
{
        time_t t = 0;
        struct tm * tmp = localtime(&t);
        char outstr[200];
        strftime(outstr,sizeof(outstr),"%T",tmp);
        printf(outstr);
        exit(EXIT_SUCCESS);
}

很明显,由于使用的是01: 00: 00. localtime() 而不是 gmtime(). 由于时间戳不包含任何时区,现在很明显,时间确实被调整到了我的时区,也就是我的时区。CET 1970年1月1日。

肮脏的变通方法是。

public static String secondsToTwentyFourHourString(long seconds)
{
    TimeZone current = TimeZone.getDefault();
    TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
    seconds *= 1000;
    try
    {return String.format("%1$TH:%1$TM:%1$TS", seconds);}
    finally
    {TimeZone.setDefault(current);}
}

更好的解决办法是使用Java 8的时间类:

public static String secondsToTwentyFourHourString(long seconds)
{
    ZonedDateTime zdt = ZonedDateTime.ofInstant(Instant.ofEpochSecond(seconds), ZoneId.of("UTC"));
    return zdt.format(DateTimeFormatter.ofPattern("HH:mm:ss")); 
}

1
投票

String格式方法需要一个日历来工作。你不能只给秒.实际上,如果你单独启动每个测试,没有一个是绿色的。

我使用了给出的响应 此处 来写一个比较经典的解决方案。

public class Entrypoint {
    public static String secondsToMinutes(long seconds)
    {
        long absSeconds = Math.abs(seconds);
        String positive = String.format(
                "%02d:%02d:%02d",
                absSeconds / 3600,
                (absSeconds % 3600) / 60,
                absSeconds % 60);
        return seconds < 0 ? "-" + positive : positive;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.