String.format、long和DateTime的转换
String.format, long and DateTime conversion
如果这个问题是重复的,我很抱歉,我没有通过 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);
}
Formatter 的 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".
但是,我收到以下 ComparisionFailure:
expected 00:00:00 but was 01:00:00
我一定是遗漏了一些明显的东西...
字符串格式方法需要日历才能工作。你不能只给秒。
实际上,如果您单独启动每个测试,其中 none 个是绿色的。
我用here的回复写了一个比较经典的解决方案:
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;
}
}
所以,要回答这个问题:
我实际上在 C:
中尝试了原生 strftime
#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);
}
由于使用 localtime()
而不是 gmtime()
,这显然返回了 01:00:00。由于时间戳不包含任何时区,现在对我来说很明显时间确实调整到了我的时区,即 1970 年 1 月 1 日的 CET
。
这个工作的肮脏解决方法是:
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's Time 类:
public static String secondsToTwentyFourHourString(long seconds)
{
ZonedDateTime zdt = ZonedDateTime.ofInstant(Instant.ofEpochSecond(seconds), ZoneId.of("UTC"));
return zdt.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
}
当您将 long
传递给 String.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"));
}
如果这个问题是重复的,我很抱歉,我没有通过 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);
}
Formatter 的 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".
但是,我收到以下 ComparisionFailure:
expected 00:00:00 but was 01:00:00
我一定是遗漏了一些明显的东西...
字符串格式方法需要日历才能工作。你不能只给秒。 实际上,如果您单独启动每个测试,其中 none 个是绿色的。
我用here的回复写了一个比较经典的解决方案:
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;
}
}
所以,要回答这个问题:
我实际上在 C:
中尝试了原生strftime
#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);
}
由于使用 localtime()
而不是 gmtime()
,这显然返回了 01:00:00。由于时间戳不包含任何时区,现在对我来说很明显时间确实调整到了我的时区,即 1970 年 1 月 1 日的 CET
。
这个工作的肮脏解决方法是:
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's Time 类:
public static String secondsToTwentyFourHourString(long seconds)
{
ZonedDateTime zdt = ZonedDateTime.ofInstant(Instant.ofEpochSecond(seconds), ZoneId.of("UTC"));
return zdt.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
}
当您将 long
传递给 String.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"));
}