Có ai biết về một thư viện Java có thể in một số trong mili giây giống như cách mà C # làm không?
Ví dụ: 123456 ms dài sẽ được in dưới dạng 4d1h3m5s.
Có ai biết về một thư viện Java có thể in một số trong mili giây giống như cách mà C # làm không?
Ví dụ: 123456 ms dài sẽ được in dưới dạng 4d1h3m5s.
%
và /
để chia số thành các phần. Gần như dễ dàng hơn một số câu trả lời được đề xuất.
/
và %
.
Câu trả lời:
Joda Time có một cách khá hay để thực hiện việc này bằng cách sử dụng PeriodFormatterBuilder .
Chiến thắng nhanh chóng: PeriodFormat.getDefault().print(duration.toPeriod());
ví dụ
//import org.joda.time.format.PeriodFormatter;
//import org.joda.time.format.PeriodFormatterBuilder;
//import org.joda.time.Duration;
Duration duration = new Duration(123456); // in milliseconds
PeriodFormatter formatter = new PeriodFormatterBuilder()
.appendDays()
.appendSuffix("d")
.appendHours()
.appendSuffix("h")
.appendMinutes()
.appendSuffix("m")
.appendSeconds()
.appendSuffix("s")
.toFormatter();
String formatted = formatter.print(duration.toPeriod());
System.out.println(formatted);
PeriodType.daysTime()
hoặc .standard()
không giúp được gì
Tôi đã xây dựng một giải pháp đơn giản, sử dụng Java 8 Duration.toString()
và một chút regex:
public static String humanReadableFormat(Duration duration) {
return duration.toString()
.substring(2)
.replaceAll("(\\d[HMS])(?!$)", "$1 ")
.toLowerCase();
}
Kết quả sẽ như sau:
- 5h
- 7h 15m
- 6h 50m 15s
- 2h 5s
- 0.1s
Nếu bạn không muốn có khoảng cách giữa, chỉ cần xóa replaceAll
.
Duration::toString
được định dạng theo tiêu chuẩn ISO 8601 được xác định rõ ràng và đã được sử dụng tốt .
.replaceAll("\\.\\d+", "")
trước cuộc gọi tới toLowerCase()
.
Apache commons-lang cung cấp một lớp hữu ích để hoàn thành việc này DurationFormatUtils
ví dụ
DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) )
=> 4: 16: 02.000 (H: m: s.millis)
DurationFormatUtils.formatDurationISO( 15362 * 1000 ) )
=> P0Y0M0DT4H16M2.000S, cf. ISO8601
JodaTime có một Period
lớp có thể đại diện cho các số lượng như vậy và có thể được hiển thị (thông qua IsoPeriodFormat
) ở định dạng ISO8601 , ví PT4D1H3M5S
dụ:
Period period = new Period(millis);
String formatted = ISOPeriodFormat.standard().print(period);
Nếu định dạng đó không phải là định dạng bạn muốn, thì PeriodFormatterBuilder
cho phép bạn tập hợp các bố cục tùy ý, bao gồm cả kiểu C # của bạn 4d1h3m5s
.
new Period(millis).toString()
sử dụng ISOPeriodFormat.standard()
theo mặc định.
Với Java 8, bạn cũng có thể sử dụng toString()
phương pháp java.time.Duration
định dạng nó mà không cần thư viện bên ngoài bằng cách sử dụng biểu diễn dựa trên ISO 8601 giây như PT8H6M12.345S.
Đây là cách bạn có thể làm điều đó bằng cách sử dụng mã JDK thuần túy:
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
long diffTime = 215081000L;
Duration duration = DatatypeFactory.newInstance().newDuration(diffTime);
System.out.printf("%02d:%02d:%02d", duration.getDays() * 24 + duration.getHours(), duration.getMinutes(), duration.getSeconds());
org.threeten.extra.AmountFormats.wordBased
Các ThreeTen-Extra dự án, được duy trì bởi Stephen Colebourne, tác giả của JSR 310, java.time , và Joda thời gian , có một AmountFormats
lớp học mà làm việc với Java 8 lớp thời gian ngày chuẩn. Tuy nhiên, nó khá dài dòng, không có tùy chọn cho đầu ra nhỏ gọn hơn.
Duration d = Duration.ofMinutes(1).plusSeconds(9).plusMillis(86);
System.out.println(AmountFormats.wordBased(d, Locale.getDefault()));
1 minute, 9 seconds and 86 milliseconds
Java 9+
Duration d1 = Duration.ofDays(0);
d1 = d1.plusHours(47);
d1 = d1.plusMinutes(124);
d1 = d1.plusSeconds(124);
System.out.println(String.format("%s d %sh %sm %ss",
d1.toDaysPart(),
d1.toHoursPart(),
d1.toMinutesPart(),
d1.toSecondsPart()));
2 ngày 1 giờ 6 phút 4 giây
Một giải pháp thay thế cho phương pháp tiếp cận người xây dựng của Joda-Time sẽ là một giải pháp dựa trên mẫu . Điều này được cung cấp bởi thư viện Time4J của tôi . Ví dụ sử dụng lớp Duration.Formatter (đã thêm một số khoảng trắng để dễ đọc hơn - xóa các khoảng trắng sẽ mang lại kiểu C # mong muốn):
IsoUnit unit = ClockUnit.MILLIS;
Duration<IsoUnit> dur = // normalized duration with multiple components
Duration.of(123456, unit).with(Duration.STD_PERIOD);
Duration.Formatter<IsoUnit> f = // create formatter/parser with optional millis
Duration.Formatter.ofPattern("D'd' h'h' m'm' s[.fff]'s'");
System.out.println(f.format(dur)); // output: 0d 0h 2m 3.456s
Bộ định dạng này cũng có thể in thời lượng java.time
-API (tuy nhiên, các tính năng chuẩn hóa của loại đó kém mạnh mẽ hơn):
System.out.println(f.format(java.time.Duration.ofMillis(123456))); // output: 0d 0h 2m 3.456s
Kỳ vọng của OP rằng "123456 ms dài sẽ được in dưới dạng 4d1h3m5s" được tính theo một cách rõ ràng là sai. Tôi cho rằng sự cẩu thả là lý do. Trình định dạng thời lượng tương tự được xác định ở trên cũng có thể được sử dụng làm trình phân tích cú pháp. Đoạn mã sau cho thấy rằng "4d1h3m5s" tương ứng với 349385000 = 1000 * (4 * 86400 + 1 * 3600 + 3 * 60 + 5)
:
System.out.println(
f.parse("4d 1h 3m 5s")
.toClockPeriodWithDaysAs24Hours()
.with(unit.only())
.getPartialAmount(unit)); // 349385000
Một cách khác là sử dụng lớp net.time4j.PrettyTime
(cũng tốt cho đầu ra được bản địa hóa và in thời gian tương đối như "hôm qua", "chủ nhật tới", "4 ngày trước", v.v.):
String s = PrettyTime.of(Locale.ENGLISH).print(dur, TextWidth.NARROW);
System.out.println(s); // output: 2m 3s 456ms
s = PrettyTime.of(Locale.ENGLISH).print(dur, TextWidth.WIDE);
System.out.println(s); // output: 2 minutes, 3 seconds, and 456 milliseconds
s = PrettyTime.of(Locale.UK).print(dur, TextWidth.WIDE);
System.out.println(s); // output: 2 minutes, 3 seconds and 456 milliseconds
Độ rộng văn bản kiểm soát xem có sử dụng chữ viết tắt hay không. Định dạng danh sách cũng có thể được kiểm soát bằng cách chọn ngôn ngữ thích hợp. Ví dụ, tiếng Anh chuẩn sử dụng dấu phẩy Oxform, trong khi ở Anh thì không. Phiên bản v5.5 mới nhất của Time4J hỗ trợ hơn 90 ngôn ngữ và sử dụng các bản dịch dựa trên kho lưu trữ CLDR (một tiêu chuẩn công nghiệp).
Một Java 8 phiên bản dựa trên câu trả lời của user678573 :
private static String humanReadableFormat(Duration duration) {
return String.format("%s days and %sh %sm %ss", duration.toDays(),
duration.toHours() - TimeUnit.DAYS.toHours(duration.toDays()),
duration.toMinutes() - TimeUnit.HOURS.toMinutes(duration.toHours()),
duration.getSeconds() - TimeUnit.MINUTES.toSeconds(duration.toMinutes()));
}
... vì không có PeriodFormatter trong Java 8 và không có các phương thức như getHours, getMinutes, ...
Tôi rất vui khi thấy một phiên bản tốt hơn cho Java 8.
Tôi nhận thấy điều này có thể không phù hợp chính xác với trường hợp sử dụng của bạn, nhưng PrettyTime có thể hữu ích ở đây.
PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
//prints: “right now”
System.out.println(p.format(new Date(1000*60*10)));
//prints: “10 minutes from now”
Duration
xác định trong tiêu chuẩn hợp lý, ISO 8601 :PnYnMnDTnHnMnS
trong đóP
có nghĩa là "Khoảng thời gian" và đánh dấu sự bắt đầu,T
phân tách phần ngày khỏi phần thời gian và ở giữa là các lần xuất hiện tùy chọn của một số với một -chữ viết tắt. Ví dụ,PT4H30M
= bốn giờ rưỡi.