Blame view

美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/ReportsDateTimeDisplayHelper.cs 7.38 KB
49755ef0   李曜臣   6-12代码优化
1
2
  using System.Globalization;
  
49755ef0   李曜臣   6-12代码优化
3
4
  namespace FoodLabeling.Application.Helpers;
  
49755ef0   李曜臣   6-12代码优化
5
  /// <summary>
c2bac760   李曜臣   20260709
6
  /// Reports Print Log 日期展示:统一为美式短日期 <c>MM/dd/yy</c>MM/DD/YY)。
49755ef0   李曜臣   6-12代码优化
7
  /// </summary>
49755ef0   李曜臣   6-12代码优化
8
  public static class ReportsDateTimeDisplayHelper
49755ef0   李曜臣   6-12代码优化
9
  {
c2bac760   李曜臣   20260709
10
11
      /// <summary>列表日期列统一格式(MM/DD/YY)。</summary>
      public const string DateDisplayFormat = "MM/dd/yy";
87280ae7   李曜臣   2026-0707
12
  
c2bac760   李曜臣   20260709
13
14
      /// <summary>含时分时在同日期格式后追加 HH:mm</summary>
      public const string DateTimeDisplayFormat = "MM/dd/yy HH:mm";
3b0c279a   杨鑫   合并
15
  
c2bac760   李曜臣   20260709
16
17
      /// <summary>兼容旧引用。</summary>
      public const string DisplayFormat = DateTimeDisplayFormat;
49755ef0   李曜臣   6-12代码优化
18
19
  
      private static readonly string[] ExpiryParseFormats =
49755ef0   李曜臣   6-12代码优化
20
      {
c2bac760   李曜臣   20260709
21
22
          DateTimeDisplayFormat,
          DateDisplayFormat,
3b0c279a   杨鑫   合并
23
          "MM/dd/yy",
3b0c279a   杨鑫   合并
24
          "MM/dd",
3b0c279a   杨鑫   合并
25
          "yyyy-MM-dd H:mm",
3b0c279a   杨鑫   合并
26
          "yyyy-MM-dd",
3b0c279a   杨鑫   合并
27
          "yyyy/MM/dd HH:mm",
3b0c279a   杨鑫   合并
28
          "yyyy/MM/dd",
49755ef0   李曜臣   6-12代码优化
29
          "MM/dd/yyyy hh:mm tt",
49755ef0   李曜臣   6-12代码优化
30
          "MM/dd/yyyy h:mm tt",
3b0c279a   杨鑫   合并
31
          "MM/dd/yyyy HH:mm",
49755ef0   李曜臣   6-12代码优化
32
          "MM/dd/yyyy",
49755ef0   李曜臣   6-12代码优化
33
          "M/d/yyyy hh:mm tt",
49755ef0   李曜臣   6-12代码优化
34
          "M/d/yyyy h:mm tt",
49755ef0   李曜臣   6-12代码优化
35
          "M/d/yyyy",
49755ef0   李曜臣   6-12代码优化
36
          "dd/MM/yyyy HH:mm",
49755ef0   李曜臣   6-12代码优化
37
          "dd/MM/yyyy",
49755ef0   李曜臣   6-12代码优化
38
          "d/M/yyyy HH:mm",
49755ef0   李曜臣   6-12代码优化
39
          "d/M/yyyy",
49755ef0   李曜臣   6-12代码优化
40
41
      };
  
c2bac760   李曜臣   20260709
42
      /// <summary>打印时间展示(Printed at 列):统一 MM/DD/YY</summary>
49755ef0   李曜臣   6-12代码优化
43
      public static string FormatPrintedAt(DateTime printedAt)
49755ef0   李曜臣   6-12代码优化
44
      {
49755ef0   李曜臣   6-12代码优化
45
          if (printedAt == DateTime.MinValue)
49755ef0   李曜臣   6-12代码优化
46
          {
49755ef0   李曜臣   6-12代码优化
47
              return "无";
49755ef0   李曜臣   6-12代码优化
48
49
          }
  
c2bac760   李曜臣   20260709
50
          return printedAt.ToString(DateDisplayFormat, CultureInfo.InvariantCulture);
49755ef0   李曜臣   6-12代码优化
51
52
      }
  
c2bac760   李曜臣   20260709
53
      /// <summary>保质期展示(Expiration 列):解析后统一为 <see cref="DateDisplayFormat"/> 或含时分时 <see cref="DateTimeDisplayFormat"/></summary>
3b0c279a   杨鑫   合并
54
      public static string FormatExpiryDisplay(string? raw, DateTime? anchor = null)
49755ef0   李曜臣   6-12代码优化
55
      {
49755ef0   李曜臣   6-12代码优化
56
          if (string.IsNullOrWhiteSpace(raw) || string.Equals(raw.Trim(), "无", StringComparison.Ordinal))
49755ef0   李曜臣   6-12代码优化
57
          {
49755ef0   李曜臣   6-12代码优化
58
              return "无";
49755ef0   李曜臣   6-12代码优化
59
60
          }
  
49755ef0   李曜臣   6-12代码优化
61
          var s = raw.Trim();
3b0c279a   杨鑫   合并
62
          if (TryParseToDateTime(s, out var dt))
3b0c279a   杨鑫   合并
63
          {
c2bac760   李曜臣   20260709
64
              return FormatExpiryDateTime(dt);
3b0c279a   杨鑫   合并
65
66
          }
  
c2bac760   李曜臣   20260709
67
68
          var reference = anchor ?? DateTime.Now;
          if (TryParsePartialDateTime(s, reference, out dt))
49755ef0   李曜臣   6-12代码优化
69
          {
c2bac760   李曜臣   20260709
70
              return FormatExpiryDateTime(dt);
49755ef0   李曜臣   6-12代码优化
71
72
          }
  
49755ef0   李曜臣   6-12代码优化
73
          return s;
49755ef0   李曜臣   6-12代码优化
74
75
      }
  
3b0c279a   杨鑫   合并
76
      /// <summary>合并日期片段(如 07/09)与时间片段(如 11:56),缺少年份时用 anchor 补全。</summary>
3b0c279a   杨鑫   合并
77
      public static string MergeDateAndTimeParts(string datePart, string timePart, DateTime anchor)
49755ef0   李曜臣   6-12代码优化
78
      {
3b0c279a   杨鑫   合并
79
          var date = datePart.Trim();
3b0c279a   杨鑫   合并
80
          var time = timePart.Trim();
3b0c279a   杨鑫   合并
81
          if (string.IsNullOrWhiteSpace(date))
87280ae7   李曜臣   2026-0707
82
          {
3b0c279a   杨鑫   合并
83
              return string.IsNullOrWhiteSpace(time) ? "无" : time;
3b0c279a   杨鑫   合并
84
85
          }
  
3b0c279a   杨鑫   合并
86
          if (!TryParsePartialDateTime(date, anchor, out var dt) && !TryParseToDateTime(date, out dt))
3b0c279a   杨鑫   合并
87
          {
3b0c279a   杨鑫   合并
88
              return string.IsNullOrWhiteSpace(time) ? date : $"{date} {time}";
3b0c279a   杨鑫   合并
89
90
          }
  
3b0c279a   杨鑫   合并
91
          if (!string.IsNullOrWhiteSpace(time))
3b0c279a   杨鑫   合并
92
          {
3b0c279a   杨鑫   合并
93
              var timeMatch = System.Text.RegularExpressions.Regex.Match(
3b0c279a   杨鑫   合并
94
                  time,
3b0c279a   杨鑫   合并
95
                  @"^(?<h>\d{1,2}):(?<m>\d{2})",
3b0c279a   杨鑫   合并
96
                  System.Text.RegularExpressions.RegexOptions.CultureInvariant);
3b0c279a   杨鑫   合并
97
              if (timeMatch.Success &&
3b0c279a   杨鑫   合并
98
                  int.TryParse(timeMatch.Groups["h"].Value, out var h) &&
3b0c279a   杨鑫   合并
99
                  int.TryParse(timeMatch.Groups["m"].Value, out var m))
3b0c279a   杨鑫   合并
100
              {
3b0c279a   杨鑫   合并
101
                  dt = new DateTime(dt.Year, dt.Month, dt.Day, h, m, 0, dt.Kind);
3b0c279a   杨鑫   合并
102
              }
87280ae7   李曜臣   2026-0707
103
104
          }
  
c2bac760   李曜臣   20260709
105
          return FormatExpiryDateTime(dt);
87280ae7   李曜臣   2026-0707
106
107
      }
  
3b0c279a   杨鑫   合并
108
      private static bool TryParsePartialDateTime(string s, DateTime anchor, out DateTime dt)
87280ae7   李曜臣   2026-0707
109
      {
87280ae7   李曜臣   2026-0707
110
          dt = default;
3b0c279a   杨鑫   合并
111
          var text = s.Trim();
3b0c279a   杨鑫   合并
112
          var timeMatch = System.Text.RegularExpressions.Regex.Match(
3b0c279a   杨鑫   合并
113
              text,
3b0c279a   杨鑫   合并
114
              @"^(?<date>\d{1,2}/\d{1,2}(?:/\d{2,4})?)\s+(?<time>\d{1,2}:\d{2})$",
3b0c279a   杨鑫   合并
115
              System.Text.RegularExpressions.RegexOptions.CultureInvariant);
3b0c279a   杨鑫   合并
116
          if (timeMatch.Success)
49755ef0   李曜臣   6-12代码优化
117
          {
3b0c279a   杨鑫   合并
118
              text = timeMatch.Groups["date"].Value;
3b0c279a   杨鑫   合并
119
              if (TryParsePartialDateOnly(text, anchor, out dt))
3b0c279a   杨鑫   合并
120
              {
3b0c279a   杨鑫   合并
121
                  var timePart = timeMatch.Groups["time"].Value;
3b0c279a   杨鑫   合并
122
                  var parts = timePart.Split(':');
3b0c279a   杨鑫   合并
123
                  if (parts.Length == 2 &&
3b0c279a   杨鑫   合并
124
                      int.TryParse(parts[0], out var h) &&
3b0c279a   杨鑫   合并
125
                      int.TryParse(parts[1], out var m))
3b0c279a   杨鑫   合并
126
                  {
3b0c279a   杨鑫   合并
127
                      dt = new DateTime(dt.Year, dt.Month, dt.Day, h, m, 0, dt.Kind);
3b0c279a   杨鑫   合并
128
                      return true;
3b0c279a   杨鑫   合并
129
                  }
3b0c279a   杨鑫   合并
130
              }
49755ef0   李曜臣   6-12代码优化
131
132
          }
  
3b0c279a   杨鑫   合并
133
          return TryParsePartialDateOnly(text, anchor, out dt);
3b0c279a   杨鑫   合并
134
135
      }
  
3b0c279a   杨鑫   合并
136
      private static bool TryParsePartialDateOnly(string s, DateTime anchor, out DateTime dt)
3b0c279a   杨鑫   合并
137
      {
3b0c279a   杨鑫   合并
138
          dt = default;
3b0c279a   杨鑫   合并
139
          var parts = s.Split('/');
3b0c279a   杨鑫   合并
140
          if (parts.Length is < 2 or > 3)
49755ef0   李曜臣   6-12代码优化
141
          {
3b0c279a   杨鑫   合并
142
              return false;
49755ef0   李曜臣   6-12代码优化
143
144
          }
  
3b0c279a   杨鑫   合并
145
          if (!int.TryParse(parts[0], out var month) || !int.TryParse(parts[1], out var day))
49755ef0   李曜臣   6-12代码优化
146
          {
3b0c279a   杨鑫   合并
147
              return false;
3b0c279a   杨鑫   合并
148
149
          }
  
3b0c279a   杨鑫   合并
150
          var year = anchor.Year;
3b0c279a   杨鑫   合并
151
          if (parts.Length == 3)
3b0c279a   杨鑫   合并
152
          {
3b0c279a   杨鑫   合并
153
              if (!int.TryParse(parts[2], out var y))
49755ef0   李曜臣   6-12代码优化
154
              {
3b0c279a   杨鑫   合并
155
                  return false;
87280ae7   李曜臣   2026-0707
156
              }
3b0c279a   杨鑫   合并
157
  
3b0c279a   杨鑫   合并
158
              year = parts[2].Length == 2 ? 2000 + y : y;
87280ae7   李曜臣   2026-0707
159
160
          }
  
3b0c279a   杨鑫   合并
161
          try
87280ae7   李曜臣   2026-0707
162
          {
3b0c279a   杨鑫   合并
163
              dt = new DateTime(year, month, day, 0, 0, 0, anchor.Kind);
87280ae7   李曜臣   2026-0707
164
              return true;
87280ae7   李曜臣   2026-0707
165
          }
3b0c279a   杨鑫   合并
166
          catch
87280ae7   李曜臣   2026-0707
167
          {
3b0c279a   杨鑫   合并
168
              return false;
87280ae7   李曜臣   2026-0707
169
          }
87280ae7   李曜臣   2026-0707
170
171
      }
  
3b0c279a   杨鑫   合并
172
      private static bool TryParseToDateTime(string s, out DateTime dt)
87280ae7   李曜臣   2026-0707
173
      {
3b0c279a   杨鑫   合并
174
          if (DateTime.TryParse(
3b0c279a   杨鑫   合并
175
                  s,
3b0c279a   杨鑫   合并
176
                  CultureInfo.InvariantCulture,
3b0c279a   杨鑫   合并
177
                  DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal,
3b0c279a   杨鑫   合并
178
                  out dt))
87280ae7   李曜臣   2026-0707
179
          {
87280ae7   李曜臣   2026-0707
180
              return true;
87280ae7   李曜臣   2026-0707
181
182
          }
  
3b0c279a   杨鑫   合并
183
          if (DateTime.TryParse(
3b0c279a   杨鑫   合并
184
                  s,
3b0c279a   杨鑫   合并
185
                  CultureInfo.GetCultureInfo("en-US"),
3b0c279a   杨鑫   合并
186
                  DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal,
3b0c279a   杨鑫   合并
187
                  out dt))
87280ae7   李曜臣   2026-0707
188
          {
87280ae7   李曜臣   2026-0707
189
              return true;
87280ae7   李曜臣   2026-0707
190
191
          }
  
3b0c279a   杨鑫   合并
192
          foreach (var fmt in ExpiryParseFormats)
87280ae7   李曜臣   2026-0707
193
          {
87280ae7   李曜臣   2026-0707
194
              if (DateTime.TryParseExact(
87280ae7   李曜臣   2026-0707
195
                      s,
87280ae7   李曜臣   2026-0707
196
                      fmt,
87280ae7   李曜臣   2026-0707
197
                      CultureInfo.InvariantCulture,
87280ae7   李曜臣   2026-0707
198
                      DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal,
3b0c279a   杨鑫   合并
199
                      out dt))
87280ae7   李曜臣   2026-0707
200
              {
87280ae7   李曜臣   2026-0707
201
                  return true;
87280ae7   李曜臣   2026-0707
202
203
              }
  
87280ae7   李曜臣   2026-0707
204
              if (DateTime.TryParseExact(
87280ae7   李曜臣   2026-0707
205
                      s,
87280ae7   李曜臣   2026-0707
206
                      fmt,
87280ae7   李曜臣   2026-0707
207
                      CultureInfo.GetCultureInfo("en-US"),
87280ae7   李曜臣   2026-0707
208
                      DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal,
3b0c279a   杨鑫   合并
209
                      out dt))
87280ae7   李曜臣   2026-0707
210
              {
49755ef0   李曜臣   6-12代码优化
211
                  return true;
49755ef0   李曜臣   6-12代码优化
212
              }
49755ef0   李曜臣   6-12代码优化
213
214
          }
  
49755ef0   李曜臣   6-12代码优化
215
          return false;
1b68006d   李曜臣   20260708
216
      }
3b0c279a   杨鑫   合并
217
  
1b68006d   李曜臣   20260708
218
219
220
221
222
223
224
225
      /// <summary>将已解析的到期时刻格式化为 Print Log 展示文案。</summary>
      public static string FormatExpiryDateTime(DateTime dt)
      {
          if (dt == DateTime.MinValue)
          {
              return "无";
          }
  
c2bac760   李曜臣   20260709
226
227
228
229
230
231
          if (dt.Hour == 0 && dt.Minute == 0 && dt.Second == 0)
          {
              return dt.ToString(DateDisplayFormat, CultureInfo.InvariantCulture);
          }
  
          return dt.ToString(DateTimeDisplayFormat, CultureInfo.InvariantCulture);
49755ef0   李曜臣   6-12代码优化
232
      }
3b0c279a   杨鑫   合并
233
  
1b68006d   李曜臣   20260708
234
235
236
237
238
239
240
241
242
243
      /// <summary>解析到期字面量(含 anchor 补全年份/时间)。</summary>
      public static bool TryParseExpiryDateTime(string s, DateTime anchor, out DateTime dt)
      {
          if (TryParseToDateTime(s, out dt))
          {
              return true;
          }
  
          return TryParsePartialDateTime(s, anchor, out dt);
      }
49755ef0   李曜臣   6-12代码优化
244
  }