OSDN Git Service

C# 8.0 のnull許容参照型を有効化
[opentween/open-tween.git] / OpenTween / DateTimeUtc.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2018 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
4 //
5 // This file is part of OpenTween.
6 //
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)
10 // any later version.
11 //
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
15 // for more details.
16 //
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.
21
22 #nullable enable
23
24 using System;
25 using System.Globalization;
26
27 namespace OpenTween
28 {
29     /// <summary>
30     /// <see cref="DateTimeKind.Utc"/> に固定された <see cref="DateTime"/> を扱うための構造体
31     /// </summary>
32     public readonly struct DateTimeUtc : IComparable<DateTimeUtc>, IEquatable<DateTimeUtc>
33     {
34         public static DateTimeUtc MinValue { get; }
35             = new DateTimeUtc(DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc));
36
37         public static DateTimeUtc MaxValue { get; }
38             = new DateTimeUtc(DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc));
39
40         public static DateTimeUtc UnixEpoch { get; }
41             = new DateTimeUtc(1970, 1, 1, 0, 0, 0);
42
43         public static DateTimeUtc Now
44             => new DateTimeUtc(DateTime.UtcNow);
45
46         private readonly DateTime datetime;
47
48         public DateTimeUtc(int year, int month, int day)
49             : this(year, month, day, hour: 0, minute: 0, second: 0)
50         {
51         }
52
53         public DateTimeUtc(int year, int month, int day, int hour, int minute, int second)
54             : this(year, month, day, hour, minute, second, millisecond: 0)
55         {
56         }
57
58         public DateTimeUtc(int year, int month, int day, int hour, int minute, int second, int millisecond)
59             : this(new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Utc))
60         {
61         }
62
63         public DateTimeUtc(DateTimeOffset datetimeOffset)
64             : this(datetimeOffset.UtcDateTime)
65         {
66         }
67
68         public DateTimeUtc(long utcTicks)
69             : this(new DateTime(utcTicks, DateTimeKind.Utc))
70         {
71         }
72
73         public DateTimeUtc(DateTime datetime)
74         {
75             if (datetime.Kind != DateTimeKind.Utc)
76                 throw new ArgumentException("datetime には UTC に変換された時刻が必須です", nameof(datetime));
77
78             this.datetime = datetime;
79         }
80
81         public long UtcTicks
82             => this.datetime.Ticks;
83
84         public long ToUnixTime()
85             => (long)((this - UnixEpoch).TotalSeconds);
86
87         public DateTimeOffset ToDateTimeOffset()
88             => new DateTimeOffset(this.datetime);
89
90         public DateTimeOffset ToLocalTime()
91             => this.ToDateTimeOffset().ToLocalTime();
92
93         public DateTime ToDateTimeUnsafe()
94             => this.datetime;
95
96         public int CompareTo(DateTimeUtc other)
97             => this.datetime.CompareTo(other.datetime);
98
99         public bool Equals(DateTimeUtc other)
100             => this == other;
101
102         public override bool Equals(object obj)
103             => obj is DateTimeUtc other && this.Equals(other);
104
105         public override int GetHashCode()
106             => this.datetime.GetHashCode();
107
108         public override string ToString()
109             => this.ToString("G");
110
111         public string ToString(string format)
112             => this.ToDateTimeOffset().ToString(format);
113
114         public string ToLocalTimeString()
115             => this.ToLocalTimeString("G");
116
117         public string ToLocalTimeString(string format)
118             => this.ToLocalTime().ToString(format);
119
120         public static DateTimeUtc operator +(DateTimeUtc a, TimeSpan b)
121             => new DateTimeUtc(a.datetime + b);
122
123         public static DateTimeUtc operator -(DateTimeUtc a, TimeSpan b)
124             => new DateTimeUtc(a.datetime - b);
125
126         public static TimeSpan operator -(DateTimeUtc a, DateTimeUtc b)
127             => a.datetime - b.datetime;
128
129         public static bool operator ==(DateTimeUtc a, DateTimeUtc b)
130             => a.datetime == b.datetime;
131
132         public static bool operator !=(DateTimeUtc a, DateTimeUtc b)
133             => a.datetime != b.datetime;
134
135         public static bool operator <(DateTimeUtc a, DateTimeUtc b)
136             => a.datetime < b.datetime;
137
138         public static bool operator <=(DateTimeUtc a, DateTimeUtc b)
139             => a.datetime <= b.datetime;
140
141         public static bool operator >(DateTimeUtc a, DateTimeUtc b)
142             => a.datetime > b.datetime;
143
144         public static bool operator >=(DateTimeUtc a, DateTimeUtc b)
145             => a.datetime >= b.datetime;
146
147         public static DateTimeUtc FromUnixTime(long unixTime)
148             => UnixEpoch + TimeSpan.FromTicks(unixTime * TimeSpan.TicksPerSecond);
149
150         public static DateTimeUtc Parse(string input, IFormatProvider formatProvider)
151             => new DateTimeUtc(DateTimeOffset.Parse(input, formatProvider, DateTimeStyles.AssumeUniversal));
152
153         public static bool TryParse(string input, IFormatProvider formatProvider, out DateTimeUtc result)
154         {
155             if (DateTimeOffset.TryParse(input, formatProvider, DateTimeStyles.AssumeUniversal, out var datetimeOffset))
156             {
157                 result = new DateTimeUtc(datetimeOffset);
158                 return true;
159             }
160
161             result = MinValue;
162             return false;
163         }
164
165         public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, out DateTimeUtc result)
166         {
167             if (DateTimeOffset.TryParseExact(input, formats, formatProvider, DateTimeStyles.AssumeUniversal, out var datetimeOffset))
168             {
169                 result = new DateTimeUtc(datetimeOffset);
170                 return true;
171             }
172
173             result = MinValue;
174             return false;
175         }
176     }
177 }