我正在使用 Angular + Typescript 构建一个 Web 应用程序。我有 ASP.NET Web API。端点之一返回具有时间跨度属性的模型。我使用字符串类型只是为了显示它,但现在我需要使用该 TimeSpan 值在画布上绘制对象,但我找不到任何有用的信息。
字符串值类似于:“00:01:05”
例如,我需要知道
TotalSeconds
。
这里是时间跨度类的 .NET C# 类似实现,支持天、小时、分钟和秒。此实现还支持负时间跨度。
const MILLIS_PER_SECOND = 1000;
const MILLIS_PER_MINUTE = MILLIS_PER_SECOND * 60; // 60,000
const MILLIS_PER_HOUR = MILLIS_PER_MINUTE * 60; // 3,600,000
const MILLIS_PER_DAY = MILLIS_PER_HOUR * 24; // 86,400,000
export class TimeSpan {
private _millis: number;
private static interval(value: number, scale: number): TimeSpan {
if (Number.isNaN(value)) {
throw new Error("value can't be NaN");
}
const tmp = value * scale;
const millis = TimeSpan.round(tmp + (value >= 0 ? 0.5 : -0.5));
if ((millis > TimeSpan.maxValue.totalMilliseconds) || (millis < TimeSpan.minValue.totalMilliseconds)) {
throw new TimeSpanOverflowError("TimeSpanTooLong");
}
return new TimeSpan(millis);
}
private static round(n: number): number {
if (n < 0) {
return Math.ceil(n);
} else if (n > 0) {
return Math.floor(n);
}
return 0;
}
private static timeToMilliseconds(hour: number, minute: number, second: number): number {
const totalSeconds = (hour * 3600) + (minute * 60) + second;
if (totalSeconds > TimeSpan.maxValue.totalSeconds || totalSeconds < TimeSpan.minValue.totalSeconds) {
throw new TimeSpanOverflowError("TimeSpanTooLong");
}
return totalSeconds * MILLIS_PER_SECOND;
}
public static get zero(): TimeSpan {
return new TimeSpan(0);
}
public static get maxValue(): TimeSpan {
return new TimeSpan(Number.MAX_SAFE_INTEGER);
}
public static get minValue(): TimeSpan {
return new TimeSpan(Number.MIN_SAFE_INTEGER);
}
public static fromDays(value: number): TimeSpan {
return TimeSpan.interval(value, MILLIS_PER_DAY);
}
public static fromHours(value: number): TimeSpan {
return TimeSpan.interval(value, MILLIS_PER_HOUR);
}
public static fromMilliseconds(value: number): TimeSpan {
return TimeSpan.interval(value, 1);
}
public static fromMinutes(value: number): TimeSpan {
return TimeSpan.interval(value, MILLIS_PER_MINUTE);
}
public static fromSeconds(value: number): TimeSpan {
return TimeSpan.interval(value, MILLIS_PER_SECOND);
}
public static fromTime(hours: number, minutes: number, seconds: number): TimeSpan;
public static fromTime(days: number, hours: number, minutes: number, seconds: number, milliseconds: number): TimeSpan;
public static fromTime(daysOrHours: number, hoursOrMinutes: number, minutesOrSeconds: number, seconds?: number, milliseconds?: number): TimeSpan {
if (milliseconds != undefined) {
return this.fromTimeStartingFromDays(daysOrHours, hoursOrMinutes, minutesOrSeconds, seconds, milliseconds);
} else {
return this.fromTimeStartingFromHours(daysOrHours, hoursOrMinutes, minutesOrSeconds);
}
}
private static fromTimeStartingFromHours(hours: number, minutes: number, seconds: number): TimeSpan {
const millis = TimeSpan.timeToMilliseconds(hours, minutes, seconds);
return new TimeSpan(millis);
}
private static fromTimeStartingFromDays(days: number, hours: number, minutes: number, seconds: number, milliseconds: number): TimeSpan {
const totalMilliSeconds = (days * MILLIS_PER_DAY) +
(hours * MILLIS_PER_HOUR) +
(minutes * MILLIS_PER_MINUTE) +
(seconds * MILLIS_PER_SECOND) +
milliseconds;
if (totalMilliSeconds > TimeSpan.maxValue.totalMilliseconds || totalMilliSeconds < TimeSpan.minValue.totalMilliseconds) {
throw new TimeSpanOverflowError("TimeSpanTooLong");
}
return new TimeSpan(totalMilliSeconds);
}
constructor(millis: number) {
this._millis = millis;
}
public get days(): number {
return TimeSpan.round(this._millis / MILLIS_PER_DAY);
}
public get hours(): number {
return TimeSpan.round((this._millis / MILLIS_PER_HOUR) % 24);
}
public get minutes(): number {
return TimeSpan.round((this._millis / MILLIS_PER_MINUTE) % 60);
}
public get seconds(): number {
return TimeSpan.round((this._millis / MILLIS_PER_SECOND) % 60);
}
public get milliseconds(): number {
return TimeSpan.round(this._millis % 1000);
}
public get totalDays(): number {
return this._millis / MILLIS_PER_DAY;
}
public get totalHours(): number {
return this._millis / MILLIS_PER_HOUR;
}
public get totalMinutes(): number {
return this._millis / MILLIS_PER_MINUTE;
}
public get totalSeconds(): number {
return this._millis / MILLIS_PER_SECOND;
}
public get totalMilliseconds(): number {
return this._millis;
}
public add(ts: TimeSpan): TimeSpan {
const result = this._millis + ts.totalMilliseconds;
return new TimeSpan(result);
}
public subtract(ts: TimeSpan): TimeSpan {
const result = this._millis - ts.totalMilliseconds;
return new TimeSpan(result);
}
}
const ts = TimeSpan.zero;
从毫秒开始
const milliseconds = 10000; // 1 second
// by using the constructor
const ts1 = new TimeSpan(milliseconds);
// or as an alternative you can use the static factory method
const ts2 = TimeSpan.fromMilliseconds(milliseconds);
从秒开始
const seconds = 86400; // 1 day
const ts = TimeSpan.fromSeconds(seconds);
从几分钟开始
const minutes = 1440; // 1 day
const ts = TimeSpan.fromMinutes(minutes);
从小时数开始
const hours = 24; // 1 day
const ts = TimeSpan.fromHours(hours);
从天
const days = 1; // 1 day
const ts = TimeSpan.fromDays(days);
从给定的小时、分钟和秒的时间开始
const hours = 1;
const minutes = 1;
const seconds = 1;
const ts = TimeSpan.fromTime(hours, minutes, seconds);
从给定天、小时、分钟、秒和毫秒的 time2 开始
const days = 1;
const hours = 1;
const minutes = 1;
const seconds = 1;
const milliseconds = 1;
const ts = TimeSpan.fromTime(days, hours, minutes, seconds, milliseconds);
从最大安全整数
const ts = TimeSpan.maxValue;
从最小安全整数开始
const ts = TimeSpan.minValue;
从最小安全整数开始
const ts = TimeSpan.minValue;
添加
const ts1 = TimeSpan.fromDays(1);
const ts2 = TimeSpan.fromHours(1);
const ts = ts1.add(ts2);
console.log(ts.days); // 1
console.log(ts.hours); // 1
console.log(ts.minutes); // 0
console.log(ts.seconds); // 0
console.log(ts.milliseconds); // 0
减去
const ts1 = TimeSpan.fromDays(1);
const ts2 = TimeSpan.fromHours(1);
const ts = ts1.subtract(ts2);
console.log(ts.days); // 0
console.log(ts.hours); // 23
console.log(ts.minutes); // 0
console.log(ts.seconds); // 0
console.log(ts.milliseconds); // 0
获取间隔
const days = 1;
const hours = 1;
const minutes = 1;
const seconds = 1;
const milliseconds = 1;
const ts = TimeSpan.fromTime2(days, hours, minutes, seconds, milliseconds);
console.log(ts.days); // 1
console.log(ts.hours); // 1
console.log(ts.minutes); // 1
console.log(ts.seconds); // 1
console.log(ts.milliseconds); // 1
console.log(ts.totalDays) // 1.0423726967592593;
console.log(ts.totalHours) // 25.016944722222224;
console.log(ts.totalMinutes) // 1501.0166833333333;
console.log(ts.totalSeconds) // 90061.001;
console.log(ts.totalMilliseconds); // 90061001;
TypeScript 没有开箱即用的 TimeSpan 类。
您可以自己实现。它会像这样:https://gist.github.com/ranwahle/e78a8859ff78bdd68055017fc5875fcb
要完成@pierre的回答,这是从字符串获取TimeSpan的一种方法:
public static fromString(value: string): TimeSpan {
var splitPoint = value.split('.');
if(splitPoint.length == 3){
var splitStrs = splitPoint[1].split(':');
return TimeSpan.fromTime(
parseInt(splitPoint[0]),
parseInt(splitStrs[0]),
parseInt(splitStrs[1]),
parseInt(splitStrs[2]),
parseInt(splitPoint[2])
);
}else{
var splitStrs = value.split(':');
return TimeSpan.fromTime(
parseInt(splitStrs[0]),
parseInt(splitStrs[1]),
parseInt(splitStrs[2])
);
}
}
我相信之前提供的
fromString
并不完整。
我创建了一个符合 .NET 8 规范的
fromString
和 toString
。
class TimeSpan {
// ...
public toString(): string {
const msFormatted = this.milliseconds.toString().padStart(3, '0').padEnd(7, '0');
// Construct the TimeSpan string
const timeSpanString =
`${this.days > 0 ? `${this.days}.` : ''}` +
`${this.hours.toString().padStart(2, '0')}:` +
`${this.minutes.toString().padStart(2, '0')}:` +
`${this.seconds.toString().padStart(2, '0')}` +
(this.milliseconds > 0 ? `.${msFormatted}` : '');
return timeSpanString;
}
public static fromJSON(value: string | TimeSpan): TimeSpan {
if (value instanceof TimeSpan) {
return value;
}
return TimeSpan.fromString(value);
}
public static fromString(value: string): TimeSpan {
// Regex to parse days, hours, minutes, seconds, and milliseconds
const timeSpanRegex = /^((?<DAYS>\d{1,})\.)?(?<HOURS>\d{2}):(?<MINUTES>\d{2}):(?<SECONDS>\d{2})(\.(?<MS>\d{7}))?$/;
const match = value.match(timeSpanRegex);
if (!match) {
throw new Error('Invalid TimeSpan format');
}
// Extract values from the matched regex groups
const { DAYS, HOURS, MINUTES, SECONDS, MS } = match.groups || {};
// Default values if any group is missing
const days = DAYS || '0';
const hours = HOURS || '00';
const minutes = MINUTES || '00';
const seconds = SECONDS || '00';
const milliseconds = MS ? MS.substring(0, 3) : '0'; // Extract milliseconds up to 3 digits
return TimeSpan.fromTime(
parseInt(days, 10),
parseInt(hours, 10),
parseInt(minutes, 10),
parseInt(seconds, 10),
parseInt(milliseconds, 10)
);
}
toJSON(): string {
return this.toString();
}
}