Update reader.

This commit is contained in:
Bruce
2026-04-06 13:09:20 +08:00
parent b562d5b5ba
commit 64f3958d7f
55 changed files with 16056 additions and 9780 deletions
+816
View File
@@ -0,0 +1,816 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Linq;
using System.Reflection;
namespace DataUtils
{
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class _I_Calendar
{
private DateTime _utcDateTime; // 存储 UTC 时间(所有算术的基础)
private Calendar _calendar; // 当前日历系统
private TimeZoneInfo _timeZone; // 当前时区
private bool _is24HourClock; // true = 24小时制,false = 12小时制
private List<string> _languages; // 语言优先级列表
private string _numeralSystem = "Latn"; // 数字系统(简化实现,仅存储)
private const long TicksPerNanosecond = 100; // 1 tick = 100 ns
// 缓存的本地时间(根据时区从 _utcDateTime 转换得到)
private DateTime _localDateTime;
// 更新本地时间(当 UTC 时间或时区改变时调用)
private void UpdateLocalDateTime ()
{
_localDateTime = TimeZoneInfo.ConvertTimeFromUtc (_utcDateTime, _timeZone);
}
// 当本地时间被修改后,同步回 UTC 时间
private void UpdateUtcDateTime ()
{
_utcDateTime = TimeZoneInfo.ConvertTimeToUtc (_localDateTime, _timeZone);
}
// 辅助:日历字段的读取
private int GetCalendarField (Func<Calendar, DateTime, int> fieldGetter)
{
return fieldGetter (_calendar, _localDateTime);
}
// 辅助:日历字段的设置(返回新的本地时间)
private DateTime SetCalendarField (DateTime currentLocal, Func<Calendar, DateTime, int, DateTime> fieldSetter, int value)
{
return fieldSetter (_calendar, currentLocal, value);
}
// 根据日历标识符创建日历实例
private static Calendar CreateCalendar (string calendarId)
{
switch (calendarId)
{
case "GregorianCalendar":
return new GregorianCalendar ();
case "HebrewCalendar":
return new HebrewCalendar ();
case "HijriCalendar":
return new HijriCalendar ();
case "JapaneseCalendar":
return new JapaneseCalendar ();
case "KoreanCalendar":
return new KoreanCalendar ();
case "TaiwanCalendar":
return new TaiwanCalendar ();
case "ThaiBuddhistCalendar":
return new ThaiBuddhistCalendar ();
case "UmAlQuraCalendar":
return new UmAlQuraCalendar ();
// 可根据需要增加更多日历
default:
return new GregorianCalendar ();
}
}
private _I_Language GetFormatCulture ()
{
if (_languages == null || _languages.Count == 0)
return new _I_Language (CultureInfo.CurrentCulture.Name);
try
{
return new _I_Language (_languages [0]);
}
catch
{
return new _I_Language (CultureInfo.CurrentCulture.Name);
}
}
private List<object> JsArrayToList (object jsArray)
{
var result = new List<object> ();
if (jsArray == null)
return result;
// JS Array 有 length 属性和数字索引器
var type = jsArray.GetType ();
int length = (int)type.InvokeMember (
"length",
BindingFlags.GetProperty,
null,
jsArray,
null);
for (int i = 0; i < length; i++)
{
object value = type.InvokeMember (
i.ToString (),
BindingFlags.GetProperty,
null,
jsArray,
null);
result.Add (value);
}
return result;
}
public _I_Calendar ()
: this (new List<string> { CultureInfo.CurrentCulture.Name },
"GregorianCalendar", "24HourClock", TimeZoneInfo.Local.Id)
{
}
public _I_Calendar (object languages)
: this (languages, "GregorianCalendar", "24HourClock", TimeZoneInfo.Local.Id)
{
}
public _I_Calendar (object languages, string calendar, string clock)
: this (languages, calendar, clock, TimeZoneInfo.Local.Id)
{
}
public _I_Calendar (object languages, string calendar, string clock, string timeZoneId)
{
_languages = languages == null ? new List<string> () : new List<string> (JsArrayToList (languages).Select (e => e as string));
if (_languages.Count == 0)
_languages.Add (CultureInfo.CurrentCulture.Name);
_calendar = CreateCalendar (calendar);
_is24HourClock = (clock == "24HourClock");
_timeZone = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);
_utcDateTime = DateTime.UtcNow;
UpdateLocalDateTime ();
}
public int Day
{
get
{
return _calendar.GetDayOfMonth (_localDateTime);
}
set
{
int currentDay = _calendar.GetDayOfMonth (_localDateTime);
if (value == currentDay) return;
// 通过加减天数来设置日期
DateTime newLocal = _calendar.AddDays (_localDateTime, value - currentDay);
_localDateTime = newLocal;
UpdateUtcDateTime ();
}
}
public int DayOfWeek
{
get
{
// 返回 0-60 表示星期日
return (int)_calendar.GetDayOfWeek (_localDateTime);
}
}
public int Era
{
get
{
return _calendar.GetEra (_localDateTime);
}
set
{
// 更改纪元较复杂,简化:仅当值不同时不做任何操作(可根据需求实现)
// 这里忽略设置,或者可以抛出 NotSupportedException
if (value != Era)
throw new NotSupportedException ("Setting Era directly is not supported in this implementation.");
}
}
public int FirstDayInThisMonth
{
get { return 1; }
}
public int FirstEra
{
get { return _calendar.GetEra (_calendar.MinSupportedDateTime); }
}
public int FirstHourInThisPeriod
{
get
{
if (_is24HourClock)
return 0;
else
return (Period == 0) ? 1 : 13;
}
}
public int FirstMinuteInThisHour
{
get { return 0; }
}
public int FirstMonthInThisYear
{
get { return 1; }
}
public int FirstPeriodInThisDay
{
get { return 0; } // 0 = AM
}
public int FirstSecondInThisMinute
{
get { return 0; }
}
public int FirstYearInThisEra
{
get
{
DateTime eraStart = _calendar.MinSupportedDateTime;
int targetEra = Era;
while (_calendar.GetEra (eraStart) != targetEra && eraStart < DateTime.MaxValue)
{
eraStart = _calendar.AddYears (eraStart, 1);
}
return _calendar.GetYear (eraStart);
}
}
public int Hour
{
get
{
int hour24 = _calendar.GetHour (_localDateTime);
if (_is24HourClock)
return hour24;
int hour12 = hour24 % 12;
return (hour12 == 0) ? 12 : hour12;
}
set
{
if (_is24HourClock)
{
if (value < 0 || value > 23)
throw new ArgumentOutOfRangeException (nameof (value), "Hour must be between 0 and 23 for 24-hour clock.");
DateTime newLocal = _localDateTime.Date.AddHours (value).AddMinutes (Minute).AddSeconds (Second);
_localDateTime = newLocal;
}
else
{
if (value < 1 || value > 12)
throw new ArgumentOutOfRangeException (nameof (value), "Hour must be between 1 and 12 for 12-hour clock.");
int hour24 = value % 12;
if (Period == 1) hour24 += 12;
DateTime newLocal = _localDateTime.Date.AddHours (hour24).AddMinutes (Minute).AddSeconds (Second);
_localDateTime = newLocal;
}
UpdateUtcDateTime ();
}
}
public bool IsDaylightSavingTime
{
get { return _timeZone.IsDaylightSavingTime (_localDateTime); }
}
public _I_List Languages
{
get { return new _I_List (_languages.AsReadOnly ().Select (e => (object)e), true) ; }
}
public int LastDayInThisMonth
{
get { return _calendar.GetDaysInMonth (_calendar.GetYear (_localDateTime), _calendar.GetMonth (_localDateTime)); }
}
public int LastEra
{
get { return _calendar.GetEra (_calendar.MaxSupportedDateTime); }
}
public int LastHourInThisPeriod
{
get
{
if (_is24HourClock)
return 23;
else
return (Period == 0) ? 11 : 23;
}
}
public int LastMinuteInThisHour
{
get { return 59; }
}
public int LastMonthInThisYear
{
get { return _calendar.GetMonthsInYear (_calendar.GetYear (_localDateTime)); }
}
public int LastPeriodInThisDay
{
get { return 1; } // 1 = PM
}
public int LastSecondInThisMinute
{
get { return 59; }
}
public int LastYearInThisEra
{
get
{
DateTime eraEnd = _calendar.MaxSupportedDateTime;
int targetEra = Era;
while (_calendar.GetEra (eraEnd) != targetEra && eraEnd > DateTime.MinValue)
{
eraEnd = _calendar.AddYears (eraEnd, -1);
}
return _calendar.GetYear (eraEnd);
}
}
public int Minute
{
get { return _calendar.GetMinute (_localDateTime); }
set
{
if (value < 0 || value > 59)
throw new ArgumentOutOfRangeException (nameof (value), "Minute must be between 0 and 59.");
DateTime newLocal = _localDateTime.AddMinutes (value - _calendar.GetMinute (_localDateTime));
_localDateTime = newLocal;
UpdateUtcDateTime ();
}
}
public int Month
{
get { return _calendar.GetMonth (_localDateTime); }
set
{
if (value < 1 || value > _calendar.GetMonthsInYear (_calendar.GetYear (_localDateTime)))
throw new ArgumentOutOfRangeException (nameof (value), "Month is out of range for current year.");
DateTime newLocal = SetCalendarField (_localDateTime, (cal, dt, val) => cal.AddMonths (dt, val - cal.GetMonth (dt)), value);
_localDateTime = newLocal;
UpdateUtcDateTime ();
}
}
public int Nanosecond
{
get
{
long ticksInSecond = _localDateTime.Ticks % TimeSpan.TicksPerSecond;
return (int)(ticksInSecond * 100); // 1 tick = 100 ns
}
set
{
if (value < 0 || value > 999999999)
throw new ArgumentOutOfRangeException (nameof (value), "Nanosecond must be between 0 and 999,999,999.");
long ticks = (_localDateTime.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond + (value / 100);
_localDateTime = new DateTime (ticks, _localDateTime.Kind);
UpdateUtcDateTime ();
}
}
public int NumberOfDaysInThisMonth
{
get { return LastDayInThisMonth; }
}
public int NumberOfEras
{
get { return _calendar.Eras.Length; }
}
public int NumberOfHoursInThisPeriod
{
get { return _is24HourClock ? 24 : 12; }
}
public int NumberOfMinutesInThisHour
{
get { return 60; }
}
public int NumberOfMonthsInThisYear
{
get { return _calendar.GetMonthsInYear (_calendar.GetYear (_localDateTime)); }
}
public int NumberOfPeriodsInThisDay
{
get { return 2; }
}
public int NumberOfSecondsInThisMinute
{
get { return 60; }
}
public int NumberOfYearsInThisEra
{
get { return LastYearInThisEra - FirstYearInThisEra + 1; }
}
public string NumeralSystem
{
get { return _numeralSystem; }
set { _numeralSystem = value; } // 简化:未实现实际数字转换
}
public int Period
{
get
{
int hour24 = _calendar.GetHour (_localDateTime);
return (hour24 >= 12) ? 1 : 0;
}
set
{
if (value != 0 && value != 1)
throw new ArgumentOutOfRangeException (nameof (value), "Period must be 0 (AM) or 1 (PM).");
int currentPeriod = Period;
if (currentPeriod == value) return;
// 切换 AM/PM:加减 12 小时
DateTime newLocal = _localDateTime.AddHours (value == 0 ? -12 : 12);
_localDateTime = newLocal;
UpdateUtcDateTime ();
}
}
public string ResolvedLanguage
{
get
{
if (_languages != null && _languages.Count > 0)
return _languages [0];
return CultureInfo.CurrentCulture.Name;
}
}
public int Second
{
get { return _calendar.GetSecond (_localDateTime); }
set
{
if (value < 0 || value > 59)
throw new ArgumentOutOfRangeException (nameof (value), "Second must be between 0 and 59.");
DateTime newLocal = _localDateTime.AddSeconds (value - _calendar.GetSecond (_localDateTime));
_localDateTime = newLocal;
UpdateUtcDateTime ();
}
}
public int Year
{
get { return _calendar.GetYear (_localDateTime); }
set
{
if (value < _calendar.GetYear (_calendar.MinSupportedDateTime) || value > _calendar.GetYear (_calendar.MaxSupportedDateTime))
throw new ArgumentOutOfRangeException (nameof (value), "Year is out of range for this calendar.");
DateTime newLocal = SetCalendarField (_localDateTime, (cal, dt, val) => cal.AddYears (dt, val - cal.GetYear (dt)), value);
_localDateTime = newLocal;
UpdateUtcDateTime ();
}
}
public void AddDays (int days)
{
_localDateTime = _calendar.AddDays (_localDateTime, days);
UpdateUtcDateTime ();
}
public void AddEras (int eras)
{
// 简化:每个纪元按 1000 年估算(实际应基于日历的纪元范围)
// 大多数情况下不应频繁使用此方法
_localDateTime = _calendar.AddYears (_localDateTime, eras * 1000);
UpdateUtcDateTime ();
}
public void AddHours (int hours)
{
_localDateTime = _localDateTime.AddHours (hours);
UpdateUtcDateTime ();
}
public void AddMinutes (int minutes)
{
_localDateTime = _localDateTime.AddMinutes (minutes);
UpdateUtcDateTime ();
}
public void AddMonths (int months)
{
_localDateTime = _calendar.AddMonths (_localDateTime, months);
UpdateUtcDateTime ();
}
public void AddNanoseconds (int nanoseconds)
{
long ticksToAdd = nanoseconds / 100;
_localDateTime = _localDateTime.AddTicks (ticksToAdd);
UpdateUtcDateTime ();
}
public void AddPeriods (int periods)
{
_localDateTime = _localDateTime.AddHours (periods * 12);
UpdateUtcDateTime ();
}
public void AddSeconds (int seconds)
{
_localDateTime = _localDateTime.AddSeconds (seconds);
UpdateUtcDateTime ();
}
public void AddWeeks (int weeks)
{
AddDays (weeks * 7);
}
public void AddYears (int years)
{
_localDateTime = _calendar.AddYears (_localDateTime, years);
UpdateUtcDateTime ();
}
public void ChangeCalendarSystem (string calendarId)
{
Calendar newCalendar = CreateCalendar (calendarId);
// 注意:日历改变不会改变绝对时间,但会影响组件(年、月、日等)
// 只需替换日历实例,_localDateTime 保持不变(但解释方式变了)
_calendar = newCalendar;
}
public void ChangeClock (string clock)
{
_is24HourClock = (clock == "24HourClock");
}
public void ChangeTimeZone (string timeZoneId)
{
_timeZone = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);
UpdateLocalDateTime (); // 重新计算本地时间(UTC 不变)
}
public _I_Calendar Clone ()
{
var clone = new _I_Calendar (_languages, GetCalendarSystem (), GetClock (), GetTimeZone ());
clone.SetDateTime (GetDateTime ());
return clone;
}
public int Compare (_I_Calendar other)
{
if (other == null) return 1;
return DateTime.Compare (this.GetDateTime (), other.GetDateTime ());
}
public static DateTime JsDateToDateTime (object jsDate)
{
if (jsDate == null)
throw new ArgumentNullException (nameof (jsDate));
Type type = jsDate.GetType ();
double milliseconds = (double)type.InvokeMember (
"getTime",
BindingFlags.InvokeMethod,
null,
jsDate,
null);
DateTimeOffset epoch = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
DateTimeOffset dateTimeOffset = epoch.AddMilliseconds (milliseconds);
return dateTimeOffset.UtcDateTime;
}
public int CompareDateTime (object other)
{
return DateTime.Compare (this.GetDateTime (), JsDateToDateTime (other));
}
public void CopyTo (_I_Calendar other)
{
if (other == null) throw new ArgumentNullException (nameof (other));
other._utcDateTime = this._utcDateTime;
other._localDateTime = this._localDateTime;
other._calendar = this._calendar;
other._timeZone = this._timeZone;
other._is24HourClock = this._is24HourClock;
other._languages = new List<string> (this._languages);
other._numeralSystem = this._numeralSystem;
}
public string DayAsPaddedString (int minDigits)
{
return Day.ToString ().PadLeft (minDigits, '0');
}
public string DayAsString ()
{
return Day.ToString ();
}
public string DayOfWeekAsSoloString ()
{
return DayOfWeekAsString ();
}
public string DayOfWeekAsSoloString (int idealLength)
{
// 简化:忽略 idealLength
return DayOfWeekAsString ();
}
public string DayOfWeekAsString ()
{
return _localDateTime.ToString ("dddd", GetFormatCulture ());
}
public string DayOfWeekAsString (int idealLength)
{
return DayOfWeekAsString ();
}
public string EraAsString ()
{
// 简化:返回纪元索引的字符串
return Era.ToString ();
}
public string EraAsString (int idealLength)
{
return EraAsString ();
}
public string GetCalendarSystem ()
{
if (_calendar is GregorianCalendar) return "GregorianCalendar";
if (_calendar is HebrewCalendar) return "HebrewCalendar";
if (_calendar is HijriCalendar) return "HijriCalendar";
if (_calendar is JapaneseCalendar) return "JapaneseCalendar";
if (_calendar is KoreanCalendar) return "KoreanCalendar";
if (_calendar is TaiwanCalendar) return "TaiwanCalendar";
if (_calendar is ThaiBuddhistCalendar) return "ThaiBuddhistCalendar";
if (_calendar is UmAlQuraCalendar) return "UmAlQuraCalendar";
return "GregorianCalendar";
}
public string GetClock ()
{
return _is24HourClock ? "24HourClock" : "12HourClock";
}
public DateTime GetDateTime ()
{
// 返回 UTC 时间
return _utcDateTime;
}
public string GetTimeZone ()
{
return _timeZone.Id;
}
public string HourAsPaddedString (int minDigits)
{
return Hour.ToString ().PadLeft (minDigits, '0');
}
public string HourAsString ()
{
return Hour.ToString ();
}
public string MinuteAsPaddedString (int minDigits)
{
return Minute.ToString ().PadLeft (minDigits, '0');
}
public string MinuteAsString ()
{
return Minute.ToString ();
}
public string MonthAsNumericString ()
{
return Month.ToString ();
}
public string MonthAsPaddedNumericString (int minDigits)
{
return Month.ToString ().PadLeft (minDigits, '0');
}
public string MonthAsSoloString ()
{
return _localDateTime.ToString ("MMMM", GetFormatCulture ());
}
public string MonthAsSoloString (int idealLength)
{
return MonthAsSoloString ();
}
public string MonthAsString ()
{
return _localDateTime.ToString ("MMM", GetFormatCulture ());
}
public string MonthAsString (int idealLength)
{
return MonthAsString ();
}
public string NanosecondAsPaddedString (int minDigits)
{
return Nanosecond.ToString ().PadLeft (minDigits, '0');
}
public string NanosecondAsString ()
{
return Nanosecond.ToString ();
}
public string PeriodAsString ()
{
return PeriodAsString (0);
}
public string PeriodAsString (int idealLength)
{
return _localDateTime.ToString ("tt", GetFormatCulture ());
}
public string SecondAsPaddedString (int minDigits)
{
return Second.ToString ().PadLeft (minDigits, '0');
}
public string SecondAsString ()
{
return Second.ToString ();
}
public void SetDateTime (DateTime value)
{
_utcDateTime = value.ToUniversalTime ();
UpdateLocalDateTime ();
}
public void SetToMax ()
{
SetDateTime (DateTime.MaxValue);
}
public void SetToMin ()
{
SetDateTime (DateTime.MinValue);
}
public void SetToNow ()
{
SetDateTime (DateTime.UtcNow);
}
public string TimeZoneAsString ()
{
return TimeZoneAsString (0);
}
public string TimeZoneAsString (int idealLength)
{
// 简化:返回标准显示名称
return _timeZone.DisplayName;
}
public string YearAsPaddedString (int minDigits)
{
return Year.ToString ().PadLeft (minDigits, '0');
}
public string YearAsString ()
{
return Year.ToString ();
}
public string YearAsTruncatedString (int remainingDigits)
{
string yearStr = Year.ToString ();
if (yearStr.Length <= remainingDigits)
return yearStr;
return yearStr.Substring (yearStr.Length - remainingDigits);
}
}
}
+2
View File
@@ -45,6 +45,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Calendar.cs" />
<Compile Include="DateTimeFormat.cs" />
<Compile Include="Download.cs" />
<Compile Include="Enumerable.cs" />
<Compile Include="HResult.cs" />
+494
View File
@@ -0,0 +1,494 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
namespace DataUtils
{
public enum YearFormat
{
None = 0,
Default = 1,
Abbreviated = 2,
Full = 3,
}
public enum MonthFormat
{
None = 0,
Default = 1,
Abbreviated = 2,
Full = 3,
Numeric = 4,
}
public enum DayFormat
{
None = 0,
Default = 1,
}
public enum DayOfWeekFormat
{
None = 0,
Default = 1,
Abbreviated = 2,
Full = 3,
}
public enum HourFormat
{
None = 0,
Default = 1,
}
public enum MinuteFormat
{
None = 0,
Default = 1,
}
public enum SecondFormat
{
None = 0,
Default = 1,
}
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class _I_DateTimeFormatter
{
// ---------- 私有字段 ----------
private string _formatTemplate; // 原始模板字符串
private string _formatPattern; // 实际用于 .NET 格式化的模式
private List<string> _languages; // 语言优先级列表
private string _geographicRegion; // 地理区域
private string _calendar = "GregorianCalendar";
private string _clock = "24HourClock";
private string _numeralSystem = "Latn";
private CultureInfo _culture; // 解析后的 CultureInfo
private string _resolvedLanguage; // 实际使用的语言
private string _resolvedGeographicRegion; // 实际使用的区域
// 存储构造时传入的枚举值(用于 IncludeXXX 属性)
private YearFormat _yearFormat = YearFormat.None;
private MonthFormat _monthFormat = MonthFormat.None;
private DayFormat _dayFormat = DayFormat.None;
private DayOfWeekFormat _dayOfWeekFormat = DayOfWeekFormat.None;
private HourFormat _hourFormat = HourFormat.None;
private MinuteFormat _minuteFormat = MinuteFormat.None;
private SecondFormat _secondFormat = SecondFormat.None;
// ---------- 辅助方法 ----------
private static string MapTemplateToPattern (string template, CultureInfo culture, string clock)
{
if (string.IsNullOrEmpty (template))
return string.Empty;
switch (template.ToLowerInvariant ())
{
case "longdate":
return culture.DateTimeFormat.LongDatePattern;
case "shortdate":
return culture.DateTimeFormat.ShortDatePattern;
case "longtime":
return culture.DateTimeFormat.LongTimePattern;
case "shorttime":
return culture.DateTimeFormat.ShortTimePattern;
case "dayofweek":
return culture.DateTimeFormat.ShortestDayNames? [0] ?? "dddd"; // 近似
case "dayofweek.full":
return "dddd";
case "dayofweek.abbreviated":
return "ddd";
case "day":
return "dd";
case "month":
return "MMMM";
case "month.full":
return "MMMM";
case "month.abbreviated":
return "MMM";
case "month.numeric":
return "MM";
case "year":
return "yyyy";
case "year.full":
return "yyyy";
case "year.abbreviated":
return "yy";
case "hour":
return clock == "24HourClock" ? "HH" : "hh";
case "minute":
return "mm";
case "second":
return "ss";
case "timezone":
return "zzz";
default:
// 如果不是预定义模板,则当作自定义模式直接返回
return template;
}
}
// 根据枚举组合构建格式模式
private static string BuildPatternFromEnums (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek,
HourFormat hour, MinuteFormat minute, SecondFormat second,
string clock, CultureInfo culture)
{
var parts = new List<string> ();
// 日期部分
if (dayOfWeek != DayOfWeekFormat.None)
{
if (dayOfWeek == DayOfWeekFormat.Abbreviated)
parts.Add ("ddd");
else // Full or Default
parts.Add ("dddd");
}
if (year != YearFormat.None)
{
if (year == YearFormat.Abbreviated)
parts.Add ("yy");
else
parts.Add ("yyyy");
}
if (month != MonthFormat.None)
{
switch (month)
{
case MonthFormat.Numeric:
parts.Add ("MM");
break;
case MonthFormat.Abbreviated:
parts.Add ("MMM");
break;
case MonthFormat.Full:
parts.Add ("MMMM");
break;
default:
parts.Add ("MM");
break;
}
}
if (day != DayFormat.None)
{
parts.Add ("dd");
}
string datePart = string.Join (" ", parts);
// 时间部分
var timeParts = new List<string> ();
if (hour != HourFormat.None)
{
if (clock == "24HourClock")
timeParts.Add ("HH");
else
timeParts.Add ("hh");
}
if (minute != MinuteFormat.None)
{
timeParts.Add ("mm");
}
if (second != SecondFormat.None)
{
timeParts.Add ("ss");
}
string timePart = timeParts.Count > 0 ? string.Join (":", timeParts) : "";
if (!string.IsNullOrEmpty (datePart) && !string.IsNullOrEmpty (timePart))
return datePart + " " + timePart;
if (!string.IsNullOrEmpty (datePart))
return datePart;
return timePart;
}
// 将 JS Date 对象转换为 DateTime
private DateTime ConvertJsDateToDateTime (object jsDate)
{
if (jsDate == null)
throw new ArgumentNullException (nameof (jsDate));
Type type = jsDate.GetType ();
// 调用 getTime() 获取毫秒数 (double)
double milliseconds = (double)type.InvokeMember (
"getTime",
BindingFlags.InvokeMethod,
null,
jsDate,
null);
// 手动计算 Unix 纪元转换(兼容低版本 .NET)
DateTime epoch = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime utcDateTime = epoch.AddMilliseconds (milliseconds);
// 返回本地时间(可根据需求调整)
return utcDateTime.ToLocalTime ();
}
// 初始化文化信息
private void InitializeCulture ()
{
string lang = (_languages != null && _languages.Count > 0) ? _languages [0] : CultureInfo.CurrentCulture.Name;
try
{
_culture = new CultureInfo (lang);
_resolvedLanguage = _culture.Name;
}
catch
{
_culture = CultureInfo.CurrentCulture;
_resolvedLanguage = _culture.Name;
}
_resolvedGeographicRegion = _geographicRegion ?? _culture.Name;
// 根据区域和语言更新格式模式(如果使用模板)
if (!string.IsNullOrEmpty (_formatTemplate))
{
_formatPattern = MapTemplateToPattern (_formatTemplate, _culture, _clock);
}
else if (_yearFormat != YearFormat.None || _monthFormat != MonthFormat.None ||
_dayFormat != DayFormat.None || _dayOfWeekFormat != DayOfWeekFormat.None ||
_hourFormat != HourFormat.None || _minuteFormat != MinuteFormat.None ||
_secondFormat != SecondFormat.None)
{
_formatPattern = BuildPatternFromEnums (_yearFormat, _monthFormat, _dayFormat, _dayOfWeekFormat,
_hourFormat, _minuteFormat, _secondFormat, _clock, _culture);
}
}
// ---------- 构造函数 ----------
public _I_DateTimeFormatter (string formatTemplate)
: this (formatTemplate, null, null, null, null)
{
}
public _I_DateTimeFormatter (string formatTemplate, IEnumerable<string> languages)
: this (formatTemplate, languages, null, null, null)
{
}
public _I_DateTimeFormatter (string formatTemplate, IEnumerable<string> languages, string geographicRegion, string calendar, string clock)
{
_formatTemplate = formatTemplate;
_languages = languages == null ? new List<string> () : new List<string> (languages);
_geographicRegion = geographicRegion;
if (!string.IsNullOrEmpty (calendar))
_calendar = calendar;
if (!string.IsNullOrEmpty (clock))
_clock = clock;
InitializeCulture ();
}
public _I_DateTimeFormatter (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek)
: this (year, month, day, dayOfWeek, HourFormat.None, MinuteFormat.None, SecondFormat.None, null, null, null, null)
{
}
public _I_DateTimeFormatter (HourFormat hour, MinuteFormat minute, SecondFormat second)
: this (YearFormat.None, MonthFormat.None, DayFormat.None, DayOfWeekFormat.None, hour, minute, second, null, null, null, null)
{
}
public _I_DateTimeFormatter (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek,
HourFormat hour, MinuteFormat minute, SecondFormat second,
IEnumerable<string> languages)
: this (year, month, day, dayOfWeek, hour, minute, second, languages, null, null, null)
{
}
public _I_DateTimeFormatter (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek,
HourFormat hour, MinuteFormat minute, SecondFormat second,
IEnumerable<string> languages, string geographicRegion, string calendar, string clock)
{
_yearFormat = year;
_monthFormat = month;
_dayFormat = day;
_dayOfWeekFormat = dayOfWeek;
_hourFormat = hour;
_minuteFormat = minute;
_secondFormat = second;
_languages = languages == null ? new List<string> () : new List<string> (languages);
_geographicRegion = geographicRegion;
if (!string.IsNullOrEmpty (calendar))
_calendar = calendar;
if (!string.IsNullOrEmpty (clock))
_clock = clock;
InitializeCulture ();
}
// ---------- 属性 ----------
public string Calendar
{
get { return _calendar; }
set
{
_calendar = value;
// 日历更改可能需要重新初始化模式,这里简化处理
}
}
public string Clock
{
get { return _clock; }
set
{
_clock = value;
InitializeCulture (); // 重新生成模式(因为小时格式可能变化)
}
}
public string GeographicRegion
{
get { return _geographicRegion; }
set
{
_geographicRegion = value;
InitializeCulture ();
}
}
public int IncludeDay
{
get { return (int)_dayFormat; }
}
public int IncludeDayOfWeek
{
get { return (int)_dayOfWeekFormat; }
}
public int IncludeHour
{
get { return (int)_hourFormat; }
}
public int IncludeMinute
{
get { return (int)_minuteFormat; }
}
public int IncludeMonth
{
get { return (int)_monthFormat; }
}
public int IncludeSecond
{
get { return (int)_secondFormat; }
}
public int IncludeYear
{
get { return (int)_yearFormat; }
}
public _I_List Languages
{
get { return new _I_List (_languages.AsReadOnly ().Select (e => (object)e), true); }
}
public static _I_DateTimeFormatter LongDate
{
get
{
return new _I_DateTimeFormatter ("longdate");
}
}
public static _I_DateTimeFormatter LongTime
{
get
{
return new _I_DateTimeFormatter ("longtime");
}
}
public string NumeralSystem
{
get { return _numeralSystem; }
set { _numeralSystem = value; }
}
public _I_List Patterns
{
get
{
return new _I_List (new List<string> { _formatPattern }.AsReadOnly ().Select (e => (object)e), true);
}
}
public string ResolvedGeographicRegion
{
get { return _resolvedGeographicRegion; }
}
public string ResolvedLanguage
{
get { return _resolvedLanguage; }
}
public static _I_DateTimeFormatter ShortDate
{
get
{
return new _I_DateTimeFormatter ("shortdate");
}
}
public static _I_DateTimeFormatter ShortTime
{
get
{
return new _I_DateTimeFormatter ("shorttime");
}
}
public string Template
{
get
{
if (!string.IsNullOrEmpty (_formatTemplate))
return _formatTemplate;
// 从枚举组合生成模板描述(简化)
return _formatPattern;
}
}
// ---------- 方法 ----------
public string FormatC (DateTime dateTime)
{
return dateTime.ToString (_formatPattern, _culture);
}
public string FormatC (DateTime dateTime, string timeZoneId)
{
if (!string.IsNullOrEmpty (timeZoneId))
{
try
{
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);
DateTime targetTime = TimeZoneInfo.ConvertTime (dateTime, tzi);
return targetTime.ToString (_formatPattern, _culture);
}
catch
{
// 时区无效,回退到原始时间
return dateTime.ToString (_formatPattern, _culture);
}
}
return dateTime.ToString (_formatPattern, _culture);
}
// 为方便 JS 调用,提供接受 object 的重载(自动识别 JS Date)
public string Format (object jsDate)
{
DateTime dt = ConvertJsDateToDateTime (jsDate);
return FormatC (dt);
}
public string FormatWithTimeZone (object jsDate, string timeZoneId)
{
DateTime dt = ConvertJsDateToDateTime (jsDate);
return FormatC (dt, timeZoneId);
}
}
}
+15 -1
View File
@@ -10,7 +10,7 @@ namespace DataUtils
{
[ComVisible (true)]
[InterfaceType (ComInterfaceType.InterfaceIsDual)]
public interface _I_Enumerable
public interface _I_Enumerable: IDisposable
{
int Length { get; set; }
object this [int index] { get; set; }
@@ -33,6 +33,9 @@ namespace DataUtils
int IndexOfKey (int key); // 按内部 key 查找
void Move (int index, int newIndex); // 移动元素
void PushAll (object [] items); // 一次性 push 多个
object Get (int index);
object Set (int index, object value);
object At (int index);
}
public class _I_List: _I_Enumerable, IList
{
@@ -43,6 +46,9 @@ namespace DataUtils
IsReadOnly = readOnly;
IsSynchronized = sync;
}
public _I_List (bool readOnly = false, bool fixedSize = false, bool sync = true) :
this (null, readOnly, fixedSize, sync)
{ }
protected List<object> _list;
protected object _lock = new object ();
public object this [int index] { get { return _list [index]; } set { _list [index] = value; } }
@@ -155,5 +161,13 @@ namespace DataUtils
return first;
}
public void Unshift (object value) => _list.Insert (0, value);
public void Dispose ()
{
_list?.Clear ();
_list = null;
}
public object Get (int index) => this [index];
public object Set (int index, object value) => this [index] = value;
public object At (int index) => this [index];
}
}
+177 -16
View File
@@ -1,29 +1,116 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
namespace DataUtils
{
internal static class NativeMethods
{
public const int LOCALE_SSHORTESTSCRIPT = 0x0000004F; // 获取四字母脚本代码
public const uint KLF_ACTIVATE = 0x00000001; // 激活键盘布局
// GetLocaleInfoW for LCID-based queries
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetLocaleInfoW (int Locale, int LCType, [Out] StringBuilder lpLCData, int cchData);
// GetLocaleInfoEx for locale name based queries
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetLocaleInfoEx (string lpLocaleName, int LCType, [Out] StringBuilder lpLCData, int cchData);
// LocaleNameToLCID - available on Vista+; fallback is to use CultureInfo
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int LocaleNameToLCID (string lpName, uint dwFlags);
// LCIDToLocaleName (Vista+)
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int LCIDToLocaleName (int Locale, [Out] StringBuilder lpName, int cchName, uint dwFlags);
[DllImport ("user32.dll")]
public static extern IntPtr GetKeyboardLayout (uint dwLayout);
[DllImport ("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr LoadKeyboardLayout (string pwszKLID, uint Flags);
}
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class _I_Language: System.Globalization.CultureInfo
{
public _I_Language (string localeName) : base (localeName) { }
public string AbbreviatedName => this.ThreeLetterISOLanguageName;
public string LanguageTag => this.IetfLanguageTag ?? this.Name;
public int LayoutDirection
{
get
{
if (base.TextInfo.IsRightToLeft) return 1;
string tag = this.LanguageTag;
bool isVerticalCandidate = false;
if (tag != null)
{
var scriptMatch = Regex.Match (tag, @"-([A-Za-z]{4})(?:-|$)");
if (scriptMatch.Success)
{
string script = scriptMatch.Groups [1].Value;
if (script == "Hani" || script == "Hira" || script == "Kana" || script == "Jpan" || script == "Kore" || script == "Hans" || script == "Hant")
isVerticalCandidate = true;
}
if (!isVerticalCandidate)
{
var regionMatch = Regex.Match (tag, @"-([A-Za-z]{2})$");
if (regionMatch.Success)
{
string region = regionMatch.Groups [1].Value.ToUpperInvariant ();
if (region == "JP" || region == "CN" || region == "TW" || region == "HK" || region == "MO" || region == "KR")
isVerticalCandidate = true;
}
}
}
if (isVerticalCandidate)
{
return 2;
}
return 0;
}
}
public string Script
{
get
{
StringBuilder sb = new StringBuilder (10);
if (NativeMethods.GetLocaleInfoEx (this.Name, NativeMethods.LOCALE_SSHORTESTSCRIPT, sb, sb.Capacity) > 0)
return sb.ToString ();
// 如果失败,尝试从语言标记中解析脚本子标记(如 "zh-Hans-CN" 中的 "Hans"
var match = Regex.Match (this.Name, @"-([A-Za-z]{4})(?:-|$)");
if (match.Success)
return match.Groups [1].Value;
return "Unknown";
}
}
public _I_List GetExtensionSubtags (string singleton)
{
if (string.IsNullOrEmpty (singleton) || singleton.Length != 1)
throw new ArgumentException ("Singleton must be a single character", nameof (singleton));
var subtags = new List<string> ();
string tag = this.LanguageTag;
string pattern = $@"-{Regex.Escape (singleton)}-([a-zA-Z0-9](?:-[a-zA-Z0-9]+)*)";
var match = Regex.Match (tag, pattern);
if (match.Success)
{
string extPart = match.Groups [1].Value;
subtags.AddRange (extPart.Split ('-'));
}
return new _I_List (subtags.Select (i => (object)i));
}
public bool TrySetInputMethodLanguageTag (string languageTag)
{
int lcid = NativeMethods.LocaleNameToLCID (languageTag, 0);
if (lcid == 0)
return false;
string klid = $"{lcid:X8}";
IntPtr hkl = NativeMethods.LoadKeyboardLayout (klid, NativeMethods.KLF_ACTIVATE);
return hkl != IntPtr.Zero;
}
}
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class _I_Locale
@@ -47,7 +134,6 @@ namespace DataUtils
}
}
}
// Current LCID (int)
public int CurrentLCID
{
@@ -63,7 +149,6 @@ namespace DataUtils
}
}
}
// Convert LCID -> locale name (e.g. 1033 -> "en-US")
public string ToLocaleName (int lcid)
{
@@ -87,7 +172,6 @@ namespace DataUtils
}
return string.Empty;
}
// Convert locale name -> LCID
public int ToLCID (string localeName)
{
@@ -111,7 +195,6 @@ namespace DataUtils
// fallback: invariant culture
return CultureInfo.InvariantCulture.LCID;
}
// Return a locale info string for given LCID and LCTYPE. LCTYPE is the Win32 LOCALE_* constant.
// Returns a string (or empty string on failure).
public object LocaleInfo (int lcid, int lctype)
@@ -177,7 +260,6 @@ namespace DataUtils
return string.Empty;
}
}
// LocaleInfoEx: query by locale name string and LCTYPE
// Returns string if available; otherwise returns the integer result code (as int) if string empty (mimic C++ behavior).
public object LocaleInfoEx (string localeName, int lctype)
@@ -239,7 +321,6 @@ namespace DataUtils
return 0;
}
}
// Helpers similar to the C++: restricted (language) and elaborated (region) codes
public string GetLocaleRestrictedCode (string localeName)
{
@@ -257,7 +338,6 @@ namespace DataUtils
return string.Empty;
}
}
public string GetLocaleElaboratedCode (string localeName)
{
if (string.IsNullOrEmpty (localeName)) localeName = CurrentLocale;
@@ -284,7 +364,6 @@ namespace DataUtils
}
return string.Empty;
}
// LCID -> combined code like "en-US" (with configurable separator)
public string LcidToLocaleCode (int lcid)
{
@@ -304,7 +383,6 @@ namespace DataUtils
}
return string.Empty;
}
// Get the user default locale name
public string GetUserDefaultLocaleName ()
{
@@ -317,7 +395,6 @@ namespace DataUtils
catch { }
return LcidToLocaleCode (CultureInfo.CurrentCulture.LCID);
}
// Get system default locale name (machine)
public string GetSystemDefaultLocaleName ()
{
@@ -330,7 +407,6 @@ namespace DataUtils
catch { }
return LcidToLocaleCode (CultureInfo.InstalledUICulture.LCID);
}
// Get computer locale code similar to C++ approach
public string GetComputerLocaleCode ()
{
@@ -350,7 +426,38 @@ namespace DataUtils
// fallback to invariant
return CultureInfo.InvariantCulture.Name ?? string.Empty;
}
public _I_List RecommendLocaleNames
{
get
{
var arr = new string [] {
System.Threading.Thread.CurrentThread.CurrentCulture.Name,
GetUserDefaultLocaleName (),
GetSystemDefaultLocaleName (),
LcidToLocaleCode (CurrentLCID),
GetLocaleRestrictedCode (System.Threading.Thread.CurrentThread.CurrentCulture.Name),
GetLocaleRestrictedCode (GetUserDefaultLocaleName ()),
GetLocaleRestrictedCode (GetSystemDefaultLocaleName ()),
"en-US",
"en"
};
var list = new _I_List ();
foreach (var loc in arr)
{
var lloc = loc.Trim ().ToLowerInvariant ();
var isfind = false;
foreach (var item in list)
{
var str = item as string;
if (string.IsNullOrWhiteSpace (str)) isfind = true;
isfind = str.Trim ().ToLowerInvariant () == lloc;
if (isfind) break;
}
if (!isfind) list.Add (loc);
}
return list;
}
}
// Compare two locale names; returns true if equal by name or LCID
public bool LocaleNameCompare (string left, string right)
{
@@ -366,8 +473,62 @@ namespace DataUtils
return false;
}
}
// Constants
private const int LOCALE_NAME_MAX_LENGTH = 85; // defined by Windows
public _I_Language CreateLanguage (string localeName) => new _I_Language (localeName);
public static string CurrentInputMethodLanguageTag
{
get
{
IntPtr hkl = NativeMethods.GetKeyboardLayout (0);
int lcid = hkl.ToInt32 () & 0xFFFF;
StringBuilder sb = new StringBuilder (85);
int result = NativeMethods.LCIDToLocaleName (lcid, sb, sb.Capacity, 0);
if (result > 0)
return sb.ToString ();
return null;
}
}
public static bool IsWellFormed (string languageTag)
{
if (string.IsNullOrEmpty (languageTag))
return false;
try
{
var _ = new CultureInfo (languageTag);
return true;
}
catch
{
return false;
}
}
public static _I_List GetMuiCompatibleLanguageListFromLanguageTags (IEnumerable<string> languageTags)
{
var result = new List<string> ();
foreach (string tag in languageTags)
{
if (string.IsNullOrEmpty (tag))
continue;
result.Add (tag);
try
{
var ci = new CultureInfo (tag);
string parent = ci.Parent.Name;
if (!string.IsNullOrEmpty (parent) && parent != tag && !result.Contains (parent))
result.Add (parent);
}
catch { }
string neutral = Regex.Replace (tag, @"-.*$", "");
if (neutral != tag && !result.Contains (neutral))
result.Add (neutral);
}
if (!result.Contains ("neutral"))
result.Add ("neutral");
return new _I_List (result.Select (t => (object)t));
}
}
}
+234 -1
View File
@@ -1,9 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -382,5 +384,236 @@ namespace DataUtils
}
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class _I_Exception: IExcep
public class _I_Exception: Exception, IDisposable
{
private Exception bex = null;
public _I_Exception (Exception ex) { bex = ex; }
public _I_Exception (string message) { bex = new Exception (message); }
public _I_Exception (string msg, Exception innerEx) { bex = new Exception (msg, innerEx); }
public override IDictionary Data => bex.Data;
public override Exception GetBaseException () => bex.GetBaseException ();
public override void GetObjectData (SerializationInfo info, StreamingContext context) => bex.GetObjectData (info, context);
public override string HelpLink
{
get { return bex.HelpLink; }
set { bex.HelpLink = value; }
}
public override string Message => bex.Message;
public override string Source
{
get { return bex.Source; }
set { bex.Source = value; }
}
public override string StackTrace => bex.StackTrace;
public override string ToString () => bex.ToString ();
public override int GetHashCode () => bex.GetHashCode ();
public override bool Equals (object obj) => bex.Equals (obj);
public void Dispose () { bex = null; }
}
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class _I_KeyValuePair: IDisposable
{
object key = null;
object value = null;
public _I_KeyValuePair (object k, object v)
{
key = k;
value = v;
}
public object Key { get { return key; } set { key = value; } }
public object Value { get { return value; } set { this.value = value; } }
public void Dispose ()
{
key = null;
value = null;
}
~_I_KeyValuePair ()
{
key = null;
value = null;
}
}
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class _I_WwwFormUrlDecoder
{
private readonly Dictionary<string, string> _params = new Dictionary<string, string> ();
public _I_WwwFormUrlDecoder (string query)
{
if (string.IsNullOrEmpty (query)) return;
if (query.StartsWith ("?")) query = query.Substring (1);
foreach (var pair in query.Split ('&'))
{
var kv = pair.Split ('=');
if (kv.Length == 2)
_params [Uri.UnescapeDataString (kv [0])] = Uri.UnescapeDataString (kv [1]);
}
}
public string GetFirstValueByName (string name)
{
string value = null;
return _params.TryGetValue (name, out value) ? value : null;
}
public int Size => _params.Count;
public _I_KeyValuePair GetAt (uint index)
{
var pair = _params.ElementAt ((int)index);
return new _I_KeyValuePair (pair.Key, pair.Value);
}
}
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class _I_Uri: Uri
{
public _I_Uri (string uri): base (uri) { }
public _I_Uri (string baseUri, string relativeUri) : base (new Uri (baseUri), relativeUri) { }
public string AbsoluteCanonicalUri => this.GetLeftPart (UriPartial.Authority) + this.PathAndQuery + this.Fragment;
public string DisplayIri => Uri.UnescapeDataString (this.OriginalString);
public string DisplayUri => Uri.UnescapeDataString (this.OriginalString);
public string Domain => ExtractDomain (this.Host);
public string Extension => System.IO.Path.GetExtension (this.AbsolutePath)?.TrimStart ('.') ?? "";
public string Password => ExtractPassword (this.UserInfo);
public string Path => this.AbsolutePath;
public object QueryParsed => new _I_WwwFormUrlDecoder (this.Query);
public string RawUri => this.OriginalString;
public string SchemeName => this.Scheme;
public bool Suspicious => !Uri.IsWellFormedUriString (this.OriginalString, UriKind.Absolute);
public string UserName => ExtractUserName (this.UserInfo);
public _I_Uri CombineUri (string relativeUri)
{
return new _I_Uri (this.AbsoluteUri, relativeUri);
}
public static string EscapeComponent (string component)
{
return Uri.EscapeDataString (component);
}
public static string UnescapeComponent (string component)
{
return Uri.UnescapeDataString (component);
}
private static string ExtractDomain (string host)
{
var parts = host.Split ('.');
if (parts.Length >= 2)
return string.Join (".", parts.Skip (1));
return host;
}
private static string ExtractUserName (string userInfo)
{
if (string.IsNullOrEmpty (userInfo)) return "";
var parts = userInfo.Split (':');
return parts [0];
}
private static string ExtractPassword (string userInfo)
{
if (string.IsNullOrEmpty (userInfo)) return "";
var parts = userInfo.Split (':');
return parts.Length > 1 ? parts [1] : "";
}
}
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class _I_Utilities
{
public _I_Uri CreateUri (string uri) => new _I_Uri (uri);
public _I_Uri CreateUri2 (string baseUri, string relaUri) => new _I_Uri (baseUri, relaUri);
public _I_Exception CreateException (string message) => new _I_Exception (message);
public _I_Exception CreateException2 (string message, _I_Exception innerEx) => new _I_Exception (message, innerEx);
public _I_Calendar CreateCalendar () => new _I_Calendar ();
public _I_Calendar CreateCalendar2 (object list) => new _I_Calendar (list);
public _I_Calendar CreateCalendar3 (object list, string arg1, string arg2) => new _I_Calendar (list, arg1, arg2);
public _I_Calendar CreateCalendar4 (object list, string arg1, string arg2, string arg3) => new _I_Calendar (list, arg1, arg2, arg3);
public _I_DateTimeFormatter CreateDateTimeFormatterFromTemplate (string formatTemplate)
{
return new _I_DateTimeFormatter (formatTemplate);
}
public _I_DateTimeFormatter CreateDateTimeFormatterFromTemplateAndLanguages (string formatTemplate, object languagesArray)
{
List<string> languages = JsArrayToStringList (languagesArray);
return new _I_DateTimeFormatter (formatTemplate, languages);
}
public _I_DateTimeFormatter CreateDateTimeFormatterFromTemplateFull (string formatTemplate, object languagesArray,
string geographicRegion, string calendar, string clock)
{
List<string> languages = JsArrayToStringList (languagesArray);
return new _I_DateTimeFormatter (formatTemplate, languages, geographicRegion, calendar, clock);
}
public _I_DateTimeFormatter CreateDateTimeFormatterFromDateEnums (int year, int month, int day, int dayOfWeek)
{
return new _I_DateTimeFormatter (
(YearFormat)year,
(MonthFormat)month,
(DayFormat)day,
(DayOfWeekFormat)dayOfWeek
);
}
public _I_DateTimeFormatter CreateDateTimeFormatterFromTimeEnums (int hour, int minute, int second)
{
return new _I_DateTimeFormatter (
(HourFormat)hour,
(MinuteFormat)minute,
(SecondFormat)second
);
}
public _I_DateTimeFormatter CreateDateTimeFormatterFromDateTimeEnums (int year, int month, int day, int dayOfWeek,
int hour, int minute, int second, object languagesArray)
{
List<string> languages = JsArrayToStringList (languagesArray);
return new _I_DateTimeFormatter (
(YearFormat)year,
(MonthFormat)month,
(DayFormat)day,
(DayOfWeekFormat)dayOfWeek,
(HourFormat)hour,
(MinuteFormat)minute,
(SecondFormat)second,
languages
);
}
public _I_DateTimeFormatter CreateDateTimeFormatterFromDateTimeEnumsFull (int year, int month, int day, int dayOfWeek,
int hour, int minute, int second, object languagesArray,
string geographicRegion, string calendar, string clock)
{
List<string> languages = JsArrayToStringList (languagesArray);
return new _I_DateTimeFormatter (
(YearFormat)year,
(MonthFormat)month,
(DayFormat)day,
(DayOfWeekFormat)dayOfWeek,
(HourFormat)hour,
(MinuteFormat)minute,
(SecondFormat)second,
languages,
geographicRegion,
calendar,
clock
);
}
private List<string> JsArrayToStringList (object jsArray)
{
var result = new List<string> ();
if (jsArray == null) return result;
Type type = jsArray.GetType ();
try
{
int length = (int)type.InvokeMember ("length", BindingFlags.GetProperty, null, jsArray, null);
for (int i = 0; i < length; i++)
{
object value = type.InvokeMember (i.ToString (), BindingFlags.GetProperty, null, jsArray, null);
if (value != null)
result.Add (value.ToString ());
}
}
catch
{
// 如果无法获取 length,则假设是单个字符串
string single = jsArray.ToString ();
if (!string.IsNullOrEmpty (single))
result.Add (single);
}
return result;
}
}
}
+9 -2
View File
@@ -297,11 +297,18 @@ namespace DataUtils
return new HttpResponse (res);
}
}
public void SendAsync (string sBody, string encoding, object pfResolve)
public void SendAsync (string sBody, string encoding, object pfResolve, object pfReject)
{
System.Threading.ThreadPool.QueueUserWorkItem (delegate
{
JsUtils.Call (pfResolve, Send (sBody, encoding));
try
{
JsUtils.Call (pfResolve, Send (sBody, encoding));
}
catch (Exception ex)
{
JsUtils.Call (pfReject, new _I_Exception (ex));
}
});
}
public void Dispose () { }