1 // OpenTween - Client of Twitter
2 // Copyright (c) 2018 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
5 // This file is part of OpenTween.
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 // You should have received a copy of the GNU General Public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
25 using System.Globalization;
30 /// <see cref="DateTimeKind.Utc"/> に固定された <see cref="DateTime"/> を扱うための構造体
32 public readonly struct DateTimeUtc : IComparable<DateTimeUtc>, IEquatable<DateTimeUtc>
34 public static DateTimeUtc MinValue { get; }
35 = new DateTimeUtc(DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc));
37 public static DateTimeUtc MaxValue { get; }
38 = new DateTimeUtc(DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc));
40 public static DateTimeUtc UnixEpoch { get; }
41 = new DateTimeUtc(1970, 1, 1, 0, 0, 0);
43 public static DateTimeUtc Now
44 => UseFakeNow ? FakeNow + FakeNowDrift : new DateTimeUtc(DateTime.UtcNow);
47 internal static bool UseFakeNow = false;
48 internal static DateTimeUtc FakeNow = DateTimeUtc.MinValue;
49 internal static TimeSpan FakeNowDrift = TimeSpan.Zero;
51 private readonly DateTime datetime;
53 public DateTimeUtc(int year, int month, int day)
54 : this(year, month, day, hour: 0, minute: 0, second: 0)
58 public DateTimeUtc(int year, int month, int day, int hour, int minute, int second)
59 : this(year, month, day, hour, minute, second, millisecond: 0)
63 public DateTimeUtc(int year, int month, int day, int hour, int minute, int second, int millisecond)
64 : this(new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Utc))
68 public DateTimeUtc(DateTimeOffset datetimeOffset)
69 : this(datetimeOffset.UtcDateTime)
73 public DateTimeUtc(long utcTicks)
74 : this(new DateTime(utcTicks, DateTimeKind.Utc))
78 public DateTimeUtc(DateTime datetime)
80 if (datetime.Kind != DateTimeKind.Utc)
81 throw new ArgumentException("datetime には UTC に変換された時刻が必須です", nameof(datetime));
83 this.datetime = datetime;
87 => this.datetime.Ticks;
89 public long ToUnixTime()
90 => (long)(this - UnixEpoch).TotalSeconds;
92 public DateTimeOffset ToDateTimeOffset()
93 => new(this.datetime);
95 public DateTimeOffset ToLocalTime()
96 => this.ToDateTimeOffset().ToLocalTime();
98 public DateTime ToDateTimeUnsafe()
101 public int CompareTo(DateTimeUtc other)
102 => this.datetime.CompareTo(other.datetime);
104 public bool Equals(DateTimeUtc other)
107 public override bool Equals(object obj)
108 => obj is DateTimeUtc other && this.Equals(other);
110 public override int GetHashCode()
111 => this.datetime.GetHashCode();
113 public override string ToString()
114 => this.ToString("G");
116 public string ToString(string format)
117 => this.ToDateTimeOffset().ToString(format);
119 public string ToLocalTimeString()
120 => this.ToLocalTimeString("G");
122 public string ToLocalTimeString(string format)
123 => this.ToLocalTime().ToString(format);
125 public static DateTimeUtc operator +(DateTimeUtc a, TimeSpan b)
126 => new(a.datetime + b);
128 public static DateTimeUtc operator -(DateTimeUtc a, TimeSpan b)
129 => new(a.datetime - b);
131 public static TimeSpan operator -(DateTimeUtc a, DateTimeUtc b)
132 => a.datetime - b.datetime;
134 public static bool operator ==(DateTimeUtc a, DateTimeUtc b)
135 => a.datetime == b.datetime;
137 public static bool operator !=(DateTimeUtc a, DateTimeUtc b)
138 => a.datetime != b.datetime;
140 public static bool operator <(DateTimeUtc a, DateTimeUtc b)
141 => a.datetime < b.datetime;
143 public static bool operator <=(DateTimeUtc a, DateTimeUtc b)
144 => a.datetime <= b.datetime;
146 public static bool operator >(DateTimeUtc a, DateTimeUtc b)
147 => a.datetime > b.datetime;
149 public static bool operator >=(DateTimeUtc a, DateTimeUtc b)
150 => a.datetime >= b.datetime;
152 public static DateTimeUtc FromUnixTime(long unixTime)
153 => UnixEpoch + TimeSpan.FromTicks(unixTime * TimeSpan.TicksPerSecond);
155 public static DateTimeUtc FromUnixTimeMilliseconds(long unixTimeMs)
156 => UnixEpoch + TimeSpan.FromTicks(unixTimeMs * TimeSpan.TicksPerMillisecond);
158 public static DateTimeUtc Parse(string input, IFormatProvider formatProvider)
159 => new(DateTimeOffset.Parse(input, formatProvider, DateTimeStyles.AssumeUniversal));
161 public static bool TryParse(string input, IFormatProvider formatProvider, out DateTimeUtc result)
163 if (DateTimeOffset.TryParse(input, formatProvider, DateTimeStyles.AssumeUniversal, out var datetimeOffset))
165 result = new DateTimeUtc(datetimeOffset);
173 public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, out DateTimeUtc result)
175 if (DateTimeOffset.TryParseExact(input, formats, formatProvider, DateTimeStyles.AssumeUniversal, out var datetimeOffset))
177 result = new DateTimeUtc(datetimeOffset);