-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathDueDate.cs
206 lines (186 loc) · 7.14 KB
/
DueDate.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
using System;
using System.Globalization;
using System.Text.Json.Serialization;
namespace Todoist.Net.Models
{
/// <summary>
/// Represents due dates for tasks and reminders.
/// </summary>
public class DueDate
{
private const string FullDayEventDateFormat = "yyyy-MM-dd";
private const string DefaultEventDateFormat = "yyyy-MM-ddTHH:mm:ssK";
[JsonConstructor]
internal DueDate()
{
}
/// <summary>
/// Gets the date time.
/// </summary>
/// <value>
/// The date time.
/// </value>
[JsonIgnore]
public DateTime? Date { get; internal set; }
/// <summary>
/// Gets a value indicating whether this instance is full day.
/// </summary>
/// <value>
/// <c>true</c> if this instance is full day; otherwise, <c>false</c>.
/// </value>
[JsonIgnore]
public bool IsFullDay { get; internal set; }
/// <summary>
/// Gets a value indicating whether this instance is recurring.
/// </summary>
/// <value>
/// <c>true</c> if this instance is recurring; otherwise, <c>false</c>.
/// </value>
[JsonPropertyName("is_recurring")]
public bool? IsRecurring { get; internal set; }
/// <summary>
/// Gets the language.
/// </summary>
/// <value>
/// The language.
/// </value>
[JsonPropertyName("lang")]
public Language Language { get; internal set; }
/// <summary>
/// Gets the text.
/// </summary>
/// <value>
/// The text.
/// </value>
[JsonPropertyName("string")]
public string Text { get; internal set; }
/// <summary>
/// Gets the timezone.
/// </summary>
/// <value>
/// The timezone.
/// </value>
[JsonPropertyName("timezone")]
public string Timezone { get; internal set; }
/// <summary>
/// Gets or sets the string date.
/// </summary>
/// <value>
/// The string date.
/// </value>
/// <remarks>
/// Format date according this rules https://developer.todoist.com/sync/v9/?shell#due-dates
/// </remarks>
[JsonInclude]
[JsonPropertyName("date")]
internal string StringDate
{
get
{
if (Date == null)
{
return null;
}
if (IsFullDay)
{
return Date.Value.ToString(FullDayEventDateFormat);
}
return Date.Value.ToString(DefaultEventDateFormat);
}
set
{
if (DateTime.TryParseExact(value, FullDayEventDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date))
{
IsFullDay = true;
Date = date;
return;
}
Date = DateTime.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
}
}
/// <summary>
/// Creates a new instance of <see cref="DueDate"/> from text (every day; each Monday).
/// </summary>
/// <remarks>
/// See <see href="https://developer.todoist.com/sync/v9/#due-dates">Todoist documentation</see> for more information.
/// </remarks>
/// <param name="text">The human-readable representation of due date (every day; each Monday)</param>
/// <param name="language">The language of the text.</param>
/// <returns>The created <see cref="DueDate"/> instance.</returns>
public static DueDate FromText(string text, Language language = null) => new DueDate
{
Text = text,
Language = language
};
/// <summary>
/// Creates a full-day <see cref="DueDate"/>.
/// </summary>
/// <param name="date">The full-day date.</param>
/// <remarks>
/// <para>
/// Only the date component of the given <see cref="DateTime"/> is used, and any time data is truncated.
/// </para>
/// <para>
/// See <see href="https://developer.todoist.com/sync/v9/#due-dates">Todoist documentation</see> for more information.
/// </para>
/// </remarks>
/// <returns>The created <see cref="DueDate"/> instance.</returns>
public static DueDate CreateFullDay(DateTime date) => new DueDate
{
Date = date.Date,
IsFullDay = true
};
/// <summary>
/// Creates a floating <see cref="DueDate"/>.
/// </summary>
/// <param name="dateTime">The floating date.</param>
/// <remarks>
/// <para>
/// The given <see cref="DateTime"/> is treated as <see cref="DateTimeKind.Unspecified"/>, and any timezone data is truncated.
/// </para>
/// <para>
/// Floating due dates always represent an event in the current user's timezone.
/// <br/>
/// Note that it's not quite compatible with <see href="https://datatracker.ietf.org/doc/html/rfc3339">RFC 3339</see>,
/// because the concept of timezone is not applicable to this object.
/// </para>
/// <para>
/// See <see href="https://developer.todoist.com/sync/v9/#due-dates">Todoist documentation</see> for more information.
/// </para>
/// </remarks>
/// <returns>The created <see cref="DueDate"/> instance.</returns>
public static DueDate CreateFloating(DateTime dateTime) => new DueDate
{
Date = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified), // Floating dates are unspecified.
IsFullDay = false
};
/// <summary>
/// Creates a fixed timezone <see cref="DueDate"/>.
/// </summary>
/// <param name="dateTime">The fixed timezone date.</param>
/// <param name="timezone">The timezone of the due instance.</param>
/// <remarks>
/// <para>
/// Fixed due date is stored in UTC, hence, <see cref="DateTime"/> of kind <see cref="DateTimeKind.Unspecified"/> is assumed UTC,
/// <br/>and <see cref="DateTime"/> of kind <see cref="DateTimeKind.Local"/> is converted to UTC based on the system timezone.
/// </para>
/// <para>
/// See <see href="https://developer.todoist.com/sync/v9/#due-dates">Todoist documentation</see> for more information.
/// </para>
/// </remarks>
/// <returns>The created <see cref="DueDate"/> instance.</returns>
public static DueDate CreateFixedTimeZone(DateTime dateTime, string timezone)
{
if (dateTime.Kind == DateTimeKind.Unspecified)
{
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); // Unspecified dates are assumed UTC.
}
return new DueDate
{
Date = dateTime.ToUniversalTime(), // Local dates are converted to UTC.
IsFullDay = false,
Timezone = timezone
};
}
}
}