SubtitleEdit/libse/TimeCode.cs

284 lines
9.4 KiB
C#
Raw Normal View History

2016-02-08 21:11:03 +01:00
using Nikse.SubtitleEdit.Core.SubtitleFormats;
using System;
using System.Globalization;
namespace Nikse.SubtitleEdit.Core
{
public class TimeCode
{
private static readonly char[] TimeSplitChars = new[] { ':', ',', '.' };
2016-02-08 21:11:03 +01:00
public const double BaseUnit = 1000.0; // Base unit of time
private double _totalMilliseconds;
public bool IsMaxTime => Math.Abs(_totalMilliseconds - MaxTimeTotalMilliseconds) < 0.01;
public const double MaxTimeTotalMilliseconds = 359999999; // new TimeCode(99, 59, 59, 999).TotalMilliseconds
2016-02-08 21:11:03 +01:00
public static TimeCode FromSeconds(double seconds)
{
return new TimeCode(seconds * BaseUnit);
}
public static double ParseToMilliseconds(string text)
{
string[] parts = text.Split(TimeSplitChars, StringSplitOptions.RemoveEmptyEntries);
2016-02-08 21:11:03 +01:00
if (parts.Length == 4)
{
int hours;
int minutes;
int seconds;
int milliseconds;
if (int.TryParse(parts[0], out hours) && int.TryParse(parts[1], out minutes) && int.TryParse(parts[2], out seconds) && int.TryParse(parts[3], out milliseconds))
{
return new TimeSpan(0, hours, minutes, seconds, milliseconds).TotalMilliseconds;
}
}
return 0;
}
public static double ParseHHMMSSFFToMilliseconds(string text)
{
string[] parts = text.Split(TimeSplitChars, StringSplitOptions.RemoveEmptyEntries);
2016-02-08 21:11:03 +01:00
if (parts.Length == 4)
{
int hours;
int minutes;
int seconds;
int frames;
if (int.TryParse(parts[0], out hours) && int.TryParse(parts[1], out minutes) && int.TryParse(parts[2], out seconds) && int.TryParse(parts[3], out frames))
{
return new TimeCode(hours, minutes, seconds, SubtitleFormat.FramesToMillisecondsMax999(frames)).TotalMilliseconds;
}
}
return 0;
}
2017-05-05 18:20:57 +02:00
public TimeCode()
{
}
2016-02-08 21:11:03 +01:00
public TimeCode(TimeSpan timeSpan)
{
_totalMilliseconds = timeSpan.TotalMilliseconds;
}
public TimeCode(double totalMilliseconds)
{
_totalMilliseconds = totalMilliseconds;
}
2016-02-27 00:35:48 +01:00
public TimeCode(int hours, int minutes, int seconds, int milliseconds)
2016-02-08 21:11:03 +01:00
{
2016-02-27 00:35:48 +01:00
_totalMilliseconds = hours * 60 * 60 * BaseUnit + minutes * 60 * BaseUnit + seconds * BaseUnit + milliseconds;
2016-02-08 21:11:03 +01:00
}
public int Hours
{
get
{
var ts = TimeSpan;
return ts.Hours + ts.Days * 24;
}
set
{
var ts = TimeSpan;
2016-11-26 19:08:52 +01:00
_totalMilliseconds = new TimeSpan(ts.Days, value, ts.Minutes, ts.Seconds, ts.Milliseconds).TotalMilliseconds;
2016-02-08 21:11:03 +01:00
}
}
public int Minutes
{
get
{
return TimeSpan.Minutes;
}
set
{
var ts = TimeSpan;
2016-11-26 19:08:52 +01:00
_totalMilliseconds = new TimeSpan(ts.Days, ts.Hours, value, ts.Seconds, ts.Milliseconds).TotalMilliseconds;
2016-02-08 21:11:03 +01:00
}
}
public int Seconds
{
get
{
return TimeSpan.Seconds;
}
set
{
var ts = TimeSpan;
2016-11-26 19:08:52 +01:00
_totalMilliseconds = new TimeSpan(ts.Days, ts.Hours, ts.Minutes, value, ts.Milliseconds).TotalMilliseconds;
2016-02-08 21:11:03 +01:00
}
}
public int Milliseconds
{
get
{
return TimeSpan.Milliseconds;
}
set
{
var ts = TimeSpan;
2016-11-26 19:08:52 +01:00
_totalMilliseconds = new TimeSpan(ts.Days, ts.Hours, ts.Minutes, ts.Seconds, value).TotalMilliseconds;
2016-02-08 21:11:03 +01:00
}
}
public double TotalMilliseconds
{
get { return _totalMilliseconds; }
set { _totalMilliseconds = value; }
}
public double TotalSeconds
{
get { return _totalMilliseconds / BaseUnit; }
set { _totalMilliseconds = value * BaseUnit; }
}
public TimeSpan TimeSpan
{
get
{
return TimeSpan.FromMilliseconds(_totalMilliseconds);
}
set
{
_totalMilliseconds = value.TotalMilliseconds;
}
}
2017-12-10 22:18:13 +01:00
2017-05-05 18:20:57 +02:00
public override string ToString() => ToString(false);
2016-02-08 21:11:03 +01:00
public string ToString(bool localize)
{
var ts = TimeSpan;
string decimalSeparator = localize ? CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator : ",";
string s = string.Format("{0:00}:{1:00}:{2:00}{3}{4:000}", ts.Hours + ts.Days * 24, ts.Minutes, ts.Seconds, decimalSeparator, ts.Milliseconds);
return PrefixSign(s);
2016-02-08 21:11:03 +01:00
}
public string ToShortString(bool localize = false)
{
var ts = TimeSpan;
string decimalSeparator = localize ? CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator : ",";
string s;
if (ts.Minutes == 0 && ts.Hours == 0 && ts.Days == 0)
2019-01-19 14:40:37 +01:00
{
2016-02-08 21:11:03 +01:00
s = string.Format("{0:0}{1}{2:000}", ts.Seconds, decimalSeparator, ts.Milliseconds);
2019-01-19 14:40:37 +01:00
}
2016-02-08 21:11:03 +01:00
else if (ts.Hours == 0 && ts.Days == 0)
2019-01-19 14:40:37 +01:00
{
2016-02-08 21:11:03 +01:00
s = string.Format("{0:0}:{1:00}{2}{3:000}", ts.Minutes, ts.Seconds, decimalSeparator, ts.Milliseconds);
2019-01-19 14:40:37 +01:00
}
2016-02-08 21:11:03 +01:00
else
2019-01-19 14:40:37 +01:00
{
2016-02-08 21:11:03 +01:00
s = string.Format("{0:0}:{1:00}:{2:00}{3}{4:000}", ts.Hours + ts.Days * 24, ts.Minutes, ts.Seconds, decimalSeparator, ts.Milliseconds);
2019-01-19 14:40:37 +01:00
}
return PrefixSign(s);
2016-02-08 21:11:03 +01:00
}
public string ToShortStringHHMMSSFF()
{
string s = ToHHMMSSFF();
string pre = string.Empty;
if (s.StartsWith('-'))
{
pre = "-";
s = s.TrimStart('-');
}
int j = 0;
2017-05-05 18:20:57 +02:00
int len = s.Length;
2017-02-23 10:06:50 +01:00
while (j + 6 < len && s[j] == '0' && s[j + 1] == '0' && s[j + 2] == ':')
{
j += 3;
2017-02-23 10:06:50 +01:00
}
s = j > 0 ? s.Substring(j) : s;
return pre + s;
2016-02-08 21:11:03 +01:00
}
public string ToHHMMSSFF()
{
string s;
2016-02-08 21:11:03 +01:00
var ts = TimeSpan;
2016-02-25 07:41:49 +01:00
var frames = Math.Round(ts.Milliseconds / (BaseUnit / Configuration.Settings.General.CurrentFrameRate));
2016-02-08 21:11:03 +01:00
if (frames >= Configuration.Settings.General.CurrentFrameRate - 0.001)
2019-01-19 14:40:37 +01:00
{
s = string.Format("{0:00}:{1:00}:{2:00}:{3:00}", ts.Days * 24 + ts.Hours, ts.Minutes, ts.Seconds + 1, 0);
2019-01-19 14:40:37 +01:00
}
else
2019-01-19 14:40:37 +01:00
{
s = string.Format("{0:00}:{1:00}:{2:00}:{3:00}", ts.Days * 24 + ts.Hours, ts.Minutes, ts.Seconds, SubtitleFormat.MillisecondsToFramesMaxFrameRate(ts.Milliseconds));
2019-01-19 14:40:37 +01:00
}
return PrefixSign(s);
2016-02-08 21:11:03 +01:00
}
2016-08-11 12:36:19 +02:00
public string ToSSFF()
{
string s;
var ts = TimeSpan;
var frames = Math.Round(ts.Milliseconds / (BaseUnit / Configuration.Settings.General.CurrentFrameRate));
if (frames >= Configuration.Settings.General.CurrentFrameRate - 0.001)
2019-01-19 14:40:37 +01:00
{
s = string.Format("{0:00}:{1:00}", ts.Seconds + 1, 0);
2019-01-19 14:40:37 +01:00
}
else
2019-01-19 14:40:37 +01:00
{
s = string.Format("{0:00}:{1:00}", ts.Seconds, SubtitleFormat.MillisecondsToFramesMaxFrameRate(ts.Milliseconds));
2019-01-19 14:40:37 +01:00
}
return PrefixSign(s);
}
2016-02-08 21:11:03 +01:00
public string ToHHMMSSPeriodFF()
{
string s;
2016-02-08 21:11:03 +01:00
var ts = TimeSpan;
2016-02-25 07:41:49 +01:00
var frames = Math.Round(ts.Milliseconds / (BaseUnit / Configuration.Settings.General.CurrentFrameRate));
2016-02-08 21:11:03 +01:00
if (frames >= Configuration.Settings.General.CurrentFrameRate - 0.001)
2019-01-19 14:40:37 +01:00
{
s = string.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Days * 24 + ts.Hours, ts.Minutes, ts.Seconds + 1, 0);
2019-01-19 14:40:37 +01:00
}
else
2019-01-19 14:40:37 +01:00
{
s = string.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Days * 24 + ts.Hours, ts.Minutes, ts.Seconds, SubtitleFormat.MillisecondsToFramesMaxFrameRate(ts.Milliseconds));
2019-01-19 14:40:37 +01:00
}
return PrefixSign(s);
2016-02-08 21:11:03 +01:00
}
private string PrefixSign(string time) => TotalMilliseconds >= 0 ? time : $"-{time.RemoveChar('-')}";
2016-02-08 21:11:03 +01:00
public string ToDisplayString()
{
if (IsMaxTime)
2019-01-19 14:40:37 +01:00
{
2016-02-08 21:11:03 +01:00
return "-";
2019-01-19 14:40:37 +01:00
}
2016-02-08 21:11:03 +01:00
2017-05-05 18:20:57 +02:00
if (Configuration.Settings?.General.UseTimeFormatHHMMSSFF == true)
2019-01-19 14:40:37 +01:00
{
2016-02-08 21:11:03 +01:00
return ToHHMMSSFF();
2019-01-19 14:40:37 +01:00
}
2016-02-08 21:11:03 +01:00
return ToString(true);
}
public string ToShortDisplayString()
{
if (IsMaxTime)
2019-01-19 14:40:37 +01:00
{
2016-02-08 21:11:03 +01:00
return "-";
2019-01-19 14:40:37 +01:00
}
2016-02-08 21:11:03 +01:00
2017-05-05 18:20:57 +02:00
if (Configuration.Settings?.General.UseTimeFormatHHMMSSFF == true)
2019-01-19 14:40:37 +01:00
{
2016-02-08 21:11:03 +01:00
return ToShortStringHHMMSSFF();
2019-01-19 14:40:37 +01:00
}
2016-02-08 21:11:03 +01:00
return ToShortString(true);
}
}
}