DatePrototype.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. using System;
  2. using System.Globalization;
  3. using Jint.Parser.Ast;
  4. using Jint.Runtime;
  5. using Jint.Runtime.Interop;
  6. namespace Jint.Native.Date
  7. {
  8. /// <summary>
  9. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.5
  10. /// </summary>
  11. public sealed class DatePrototype : DateInstance
  12. {
  13. private DatePrototype(Engine engine)
  14. : base(engine)
  15. {
  16. }
  17. public static DatePrototype CreatePrototypeObject(Engine engine, DateConstructor dateConstructor)
  18. {
  19. var obj = new DatePrototype(engine);
  20. obj.Prototype = engine.Object.PrototypeObject;
  21. obj.Extensible = true;
  22. obj.FastAddProperty("constructor", dateConstructor, true, false, true);
  23. return obj;
  24. }
  25. public void Configure()
  26. {
  27. FastAddProperty("toString", new ClrFunctionInstance(Engine, ToString, 0), true, false, true);
  28. FastAddProperty("toDateString", new ClrFunctionInstance(Engine, ToDateString, 0), true, false, true);
  29. FastAddProperty("toTimeString", new ClrFunctionInstance(Engine, ToTimeString, 0), true, false, true);
  30. FastAddProperty("toLocaleString", new ClrFunctionInstance(Engine, ToLocaleString, 0), true, false, true);
  31. FastAddProperty("toLocaleDateString", new ClrFunctionInstance(Engine, ToLocaleDateString, 0), true, false, true);
  32. FastAddProperty("toLocaleTimeString", new ClrFunctionInstance(Engine, ToLocaleTimeString, 0), true, false, true);
  33. FastAddProperty("valueOf", new ClrFunctionInstance(Engine, ValueOf, 0), true, false, true);
  34. FastAddProperty("getTime", new ClrFunctionInstance(Engine, GetTime, 0), true, false, true);
  35. FastAddProperty("getFullYear", new ClrFunctionInstance(Engine, GetFullYear, 0), true, false, true);
  36. FastAddProperty("getUTCFullYear", new ClrFunctionInstance(Engine, GetUTCFullYear, 0), true, false, true);
  37. FastAddProperty("getMonth", new ClrFunctionInstance(Engine, GetMonth, 0), true, false, true);
  38. FastAddProperty("getUTCMonth", new ClrFunctionInstance(Engine, GetUTCMonth, 0), true, false, true);
  39. FastAddProperty("getDate", new ClrFunctionInstance(Engine, GetDate, 0), true, false, true);
  40. FastAddProperty("getUTCDate", new ClrFunctionInstance(Engine, GetUTCDate, 0), true, false, true);
  41. FastAddProperty("getDay", new ClrFunctionInstance(Engine, GetDay, 0), true, false, true);
  42. FastAddProperty("getUTCDay", new ClrFunctionInstance(Engine, GetUTCDay, 0), true, false, true);
  43. FastAddProperty("getHours", new ClrFunctionInstance(Engine, GetHours, 0), true, false, true);
  44. FastAddProperty("getUTCHours", new ClrFunctionInstance(Engine, GetUTCHours, 0), true, false, true);
  45. FastAddProperty("getMinutes", new ClrFunctionInstance(Engine, GetMinutes, 0), true, false, true);
  46. FastAddProperty("getUTCMinutes", new ClrFunctionInstance(Engine, GetUTCMinutes, 0), true, false, true);
  47. FastAddProperty("getSeconds", new ClrFunctionInstance(Engine, GetSeconds, 0), true, false, true);
  48. FastAddProperty("getUTCSeconds", new ClrFunctionInstance(Engine, GetUTCSeconds, 0), true, false, true);
  49. FastAddProperty("getMilliseconds", new ClrFunctionInstance(Engine, GetMilliseconds, 0), true, false, true);
  50. FastAddProperty("getUTCMilliseconds", new ClrFunctionInstance(Engine, GetUTCMilliseconds, 0), true, false, true);
  51. FastAddProperty("getTimezoneOffset", new ClrFunctionInstance(Engine, GetTimezoneOffset, 0), true, false, true);
  52. FastAddProperty("setTime", new ClrFunctionInstance(Engine, SetTime, 1), true, false, true);
  53. FastAddProperty("setMilliseconds", new ClrFunctionInstance(Engine, SetMilliseconds, 1), true, false, true);
  54. FastAddProperty("setUTCMilliseconds", new ClrFunctionInstance(Engine, SetUTCMilliseconds, 1), true, false, true);
  55. FastAddProperty("setSeconds", new ClrFunctionInstance(Engine, SetSeconds, 2), true, false, true);
  56. FastAddProperty("setUTCSeconds", new ClrFunctionInstance(Engine, SetUTCSeconds, 2), true, false, true);
  57. FastAddProperty("setMinutes", new ClrFunctionInstance(Engine, SetMinutes, 3), true, false, true);
  58. FastAddProperty("setUTCMinutes", new ClrFunctionInstance(Engine, SetUTCMinutes, 3), true, false, true);
  59. FastAddProperty("setHours", new ClrFunctionInstance(Engine, SetHours, 4), true, false, true);
  60. FastAddProperty("setUTCHours", new ClrFunctionInstance(Engine, SetUTCHours, 4), true, false, true);
  61. FastAddProperty("setDate", new ClrFunctionInstance(Engine, SetDate, 1), true, false, true);
  62. FastAddProperty("setUTCDate", new ClrFunctionInstance(Engine, SetUTCDate, 1), true, false, true);
  63. FastAddProperty("setMonth", new ClrFunctionInstance(Engine, SetMonth, 2), true, false, true);
  64. FastAddProperty("setUTCMonth", new ClrFunctionInstance(Engine, SetUTCMonth, 2), true, false, true);
  65. FastAddProperty("setFullYear", new ClrFunctionInstance(Engine, SetFullYear, 3), true, false, true);
  66. FastAddProperty("setUTCFullYear", new ClrFunctionInstance(Engine, SetUTCFullYear, 3), true, false, true);
  67. FastAddProperty("toUTCString", new ClrFunctionInstance(Engine, ToUTCString, 0), true, false, true);
  68. FastAddProperty("toISOString", new ClrFunctionInstance(Engine, ToISOString, 0), true, false, true);
  69. FastAddProperty("toJSON", new ClrFunctionInstance(Engine, ToJSON, 1), true, false, true);
  70. }
  71. private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)
  72. {
  73. return thisObj.TryCast<DateInstance>().PrimitiveValue;
  74. }
  75. public JsValue ToString(JsValue thisObj, JsValue[] arg2)
  76. {
  77. return thisObj.TryCast<DateInstance>().ToDateTime().ToString("F", CultureInfo.InvariantCulture);
  78. }
  79. private JsValue ToDateString(JsValue thisObj, JsValue[] arguments)
  80. {
  81. return thisObj.TryCast<DateInstance>().ToDateTime().ToString("D", CultureInfo.InvariantCulture);
  82. }
  83. private JsValue ToTimeString(JsValue thisObj, JsValue[] arguments)
  84. {
  85. return thisObj.TryCast<DateInstance>().ToDateTime().ToString("T", CultureInfo.InvariantCulture);
  86. }
  87. private JsValue ToLocaleString(JsValue thisObj, JsValue[] arguments)
  88. {
  89. return thisObj.TryCast<DateInstance>().ToDateTime().ToString("F");
  90. }
  91. private JsValue ToLocaleDateString(JsValue thisObj, JsValue[] arguments)
  92. {
  93. return thisObj.TryCast<DateInstance>().ToDateTime().ToString("D");
  94. }
  95. private JsValue ToLocaleTimeString(JsValue thisObj, JsValue[] arguments)
  96. {
  97. return thisObj.TryCast<DateInstance>().ToDateTime().ToString("T");
  98. }
  99. private JsValue GetTime(JsValue thisObj, JsValue[] arguments)
  100. {
  101. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  102. {
  103. return double.NaN;
  104. }
  105. return thisObj.TryCast<DateInstance>().PrimitiveValue;
  106. }
  107. private JsValue GetFullYear(JsValue thisObj, JsValue[] arguments)
  108. {
  109. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  110. {
  111. return double.NaN;
  112. }
  113. return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Year;
  114. }
  115. private JsValue GetUTCFullYear(JsValue thisObj, JsValue[] arguments)
  116. {
  117. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  118. {
  119. return double.NaN;
  120. }
  121. return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Year;
  122. }
  123. private JsValue GetMonth(JsValue thisObj, JsValue[] arguments)
  124. {
  125. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  126. {
  127. return double.NaN;
  128. }
  129. return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Month - 1;
  130. }
  131. private JsValue GetUTCMonth(JsValue thisObj, JsValue[] arguments)
  132. {
  133. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  134. {
  135. return double.NaN;
  136. }
  137. return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Month;
  138. }
  139. private JsValue GetDate(JsValue thisObj, JsValue[] arguments)
  140. {
  141. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  142. {
  143. return double.NaN;
  144. }
  145. return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Day;
  146. }
  147. private JsValue GetUTCDate(JsValue thisObj, JsValue[] arguments)
  148. {
  149. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  150. {
  151. return double.NaN;
  152. }
  153. return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Day;
  154. }
  155. private JsValue GetDay(JsValue thisObj, JsValue[] arguments)
  156. {
  157. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  158. {
  159. return double.NaN;
  160. }
  161. return (int)thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().DayOfWeek;
  162. }
  163. private JsValue GetUTCDay(JsValue thisObj, JsValue[] arguments)
  164. {
  165. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  166. {
  167. return double.NaN;
  168. }
  169. return (int)thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().DayOfWeek;
  170. }
  171. private JsValue GetHours(JsValue thisObj, JsValue[] arguments)
  172. {
  173. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  174. {
  175. return double.NaN;
  176. }
  177. return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Hour;
  178. }
  179. private JsValue GetUTCHours(JsValue thisObj, JsValue[] arguments)
  180. {
  181. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  182. {
  183. return double.NaN;
  184. }
  185. return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Hour;
  186. }
  187. private JsValue GetMinutes(JsValue thisObj, JsValue[] arguments)
  188. {
  189. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  190. {
  191. return double.NaN;
  192. }
  193. return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Minute;
  194. }
  195. private JsValue GetUTCMinutes(JsValue thisObj, JsValue[] arguments)
  196. {
  197. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  198. {
  199. return double.NaN;
  200. }
  201. return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Minute;
  202. }
  203. private JsValue GetSeconds(JsValue thisObj, JsValue[] arguments)
  204. {
  205. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  206. {
  207. return double.NaN;
  208. }
  209. return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Second;
  210. }
  211. private JsValue GetUTCSeconds(JsValue thisObj, JsValue[] arguments)
  212. {
  213. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  214. {
  215. return double.NaN;
  216. }
  217. return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Second;
  218. }
  219. private JsValue GetMilliseconds(JsValue thisObj, JsValue[] arguments)
  220. {
  221. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  222. {
  223. return double.NaN;
  224. }
  225. return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Millisecond;
  226. }
  227. private JsValue GetUTCMilliseconds(JsValue thisObj, JsValue[] arguments)
  228. {
  229. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  230. {
  231. return double.NaN;
  232. }
  233. return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Second;
  234. }
  235. private JsValue GetTimezoneOffset(JsValue thisObj, JsValue[] arguments)
  236. {
  237. if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
  238. {
  239. return double.NaN;
  240. }
  241. return - TimeZoneInfo.Local.GetUtcOffset(thisObj.TryCast<DateInstance>().ToDateTime()).Hours*60;
  242. }
  243. private JsValue SetTime(JsValue thisObj, JsValue[] arguments)
  244. {
  245. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.TimeClip(TypeConverter.ToNumber(arguments.At(0)));
  246. }
  247. private JsValue SetMilliseconds(JsValue thisObj, JsValue[] arguments)
  248. {
  249. var dt = thisObj.TryCast<DateInstance>().ToDateTime();
  250. dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)TypeConverter.ToNumber(arguments.At(0)), DateTimeKind.Local);
  251. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  252. }
  253. private JsValue SetUTCMilliseconds(JsValue thisObj, JsValue[] arguments)
  254. {
  255. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
  256. dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)TypeConverter.ToNumber(arguments.At(0)), DateTimeKind.Utc);
  257. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  258. }
  259. private JsValue SetSeconds(JsValue thisObj, JsValue[] arguments)
  260. {
  261. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime();
  262. var ms = arguments.At(1) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(1));
  263. dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, (int)TypeConverter.ToNumber(arguments.At(0)), (int)ms, DateTimeKind.Local);
  264. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  265. }
  266. private JsValue SetUTCSeconds(JsValue thisObj, JsValue[] arguments)
  267. {
  268. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
  269. var ms = arguments.At(1) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(1));
  270. dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, (int)TypeConverter.ToNumber(arguments.At(0)), (int)ms, DateTimeKind.Utc);
  271. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  272. }
  273. private JsValue SetMinutes(JsValue thisObj, JsValue[] arguments)
  274. {
  275. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime();
  276. var s = arguments.At(1) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(1));
  277. var ms = arguments.At(2) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(2));
  278. dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, (int)TypeConverter.ToNumber(arguments.At(0)), (int)s, (int)ms, DateTimeKind.Local);
  279. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  280. }
  281. private JsValue SetUTCMinutes(JsValue thisObj, JsValue[] arguments)
  282. {
  283. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
  284. var s = arguments.At(1) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(1));
  285. var ms = arguments.At(2) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(2));
  286. dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, (int)TypeConverter.ToNumber(arguments.At(0)), (int)s, (int)ms, DateTimeKind.Utc);
  287. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  288. }
  289. private JsValue SetHours(JsValue thisObj, JsValue[] arguments)
  290. {
  291. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime();
  292. var min = arguments.At(1) == Undefined.Instance ? dt.Minute : TypeConverter.ToNumber(arguments.At(1));
  293. var s = arguments.At(2) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(2));
  294. var ms = arguments.At(3) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(3));
  295. dt = new DateTime(dt.Year, dt.Month, dt.Day, (int)TypeConverter.ToNumber(arguments.At(0)), (int)min, (int)s, (int)ms, DateTimeKind.Local);
  296. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  297. }
  298. private JsValue SetUTCHours(JsValue thisObj, JsValue[] arguments)
  299. {
  300. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
  301. var min = arguments.At(1) == Undefined.Instance ? dt.Minute : TypeConverter.ToNumber(arguments.At(1));
  302. var s = arguments.At(2) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(2));
  303. var ms = arguments.At(3) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(3));
  304. dt = new DateTime(dt.Year, dt.Month, dt.Day, (int)TypeConverter.ToNumber(arguments.At(0)), (int)min, (int)s, (int)ms, DateTimeKind.Utc);
  305. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  306. }
  307. private JsValue SetDate(JsValue thisObj, JsValue[] arguments)
  308. {
  309. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime();
  310. dt = new DateTime(dt.Year, dt.Month, (int)TypeConverter.ToNumber(arguments.At(0)), dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
  311. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  312. }
  313. private JsValue SetUTCDate(JsValue thisObj, JsValue[] arguments)
  314. {
  315. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
  316. dt = new DateTime(dt.Year, dt.Month, (int)TypeConverter.ToNumber(arguments.At(0)), dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
  317. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  318. }
  319. private JsValue SetMonth(JsValue thisObj, JsValue[] arguments)
  320. {
  321. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
  322. var date = arguments.At(1) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(1));
  323. dt = new DateTime(dt.Year, (int)TypeConverter.ToNumber(arguments.At(0)), (int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
  324. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  325. }
  326. private JsValue SetUTCMonth(JsValue thisObj, JsValue[] arguments)
  327. {
  328. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
  329. var date = arguments.At(1) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(1));
  330. dt = new DateTime(dt.Year, (int)TypeConverter.ToNumber(arguments.At(0)), (int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
  331. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  332. }
  333. private JsValue SetFullYear(JsValue thisObj, JsValue[] arguments)
  334. {
  335. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime();
  336. var month = arguments.At(1) == Undefined.Instance ? dt.Month : TypeConverter.ToNumber(arguments.At(1));
  337. var date = arguments.At(2) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(2));
  338. dt = new DateTime((int)TypeConverter.ToNumber(arguments.At(0)), (int)month, (int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
  339. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  340. }
  341. private JsValue SetUTCFullYear(JsValue thisObj, JsValue[] arguments)
  342. {
  343. var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
  344. var month = arguments.At(1) == Undefined.Instance ? dt.Month : TypeConverter.ToNumber(arguments.At(1));
  345. var date = arguments.At(2) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(2));
  346. dt = new DateTime((int)TypeConverter.ToNumber(arguments.At(0)), (int)month, (int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
  347. return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
  348. }
  349. private JsValue ToUTCString(JsValue thisObj, JsValue[] arguments)
  350. {
  351. return thisObj.TryCast<DateInstance>(x =>
  352. {
  353. throw new JavaScriptException(Engine.TypeError);
  354. } )
  355. .ToDateTime().ToUniversalTime().ToString("r");
  356. }
  357. private JsValue ToISOString(JsValue thisObj, JsValue[] arguments)
  358. {
  359. return thisObj.TryCast<DateInstance>(x =>
  360. {
  361. throw new JavaScriptException(Engine.TypeError);
  362. })
  363. .ToDateTime().ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
  364. }
  365. private JsValue ToJSON(JsValue thisObj, JsValue[] arguments)
  366. {
  367. return thisObj.TryCast<DateInstance>(x =>
  368. {
  369. throw new JavaScriptException(Engine.TypeError);
  370. })
  371. .ToDateTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
  372. }
  373. public static double MsPerDay = 86400000;
  374. public static double MsPerHour = 3600000;
  375. /// <summary>
  376. /// 15.9.1.2
  377. /// </summary>
  378. public static double Day(double t)
  379. {
  380. return System.Math.Floor(t / MsPerDay);
  381. }
  382. /// <summary>
  383. /// 15.9.1.2
  384. /// </summary>
  385. public static double TimeWithinDay(double t)
  386. {
  387. return t % MsPerDay;
  388. }
  389. /// <summary>
  390. /// The number of days in a year
  391. /// </summary>
  392. public static double DaysInYear(double y)
  393. {
  394. if (!(y%4).Equals(0))
  395. {
  396. return 365;
  397. }
  398. if ((y%4).Equals(0) && !(y%100).Equals(100))
  399. {
  400. return 365;
  401. }
  402. if ((y%100).Equals(0) && !(y%400).Equals(100))
  403. {
  404. return 365;
  405. }
  406. if ((y%400).Equals(0))
  407. {
  408. return 366;
  409. }
  410. return 365;
  411. }
  412. /// <summary>
  413. /// The day number of the first day of the year.
  414. /// </summary>
  415. public static double DayFromYear(double y)
  416. {
  417. return 365*(y - 1970) + System.Math.Floor((y - 1969)/4) - System.Math.Floor((y - 1901)/100) +
  418. System.Math.Floor((y - 1601)/400);
  419. }
  420. /// <summary>
  421. /// The time value of the start of the year
  422. /// </summary>
  423. public static double TimeFromYear(double y)
  424. {
  425. return MsPerDay*DayFromYear(y);
  426. }
  427. /// <summary>
  428. /// The year of a time value.
  429. /// </summary>
  430. public static double YearFromTime(double t)
  431. {
  432. double upper = double.PositiveInfinity;
  433. double lower = double.NegativeInfinity;
  434. while (upper > lower)
  435. {
  436. var current = System.Math.Floor(upper + lower / 2);
  437. if (TimeFromYear(current) <= t)
  438. {
  439. lower = current;
  440. }
  441. else
  442. {
  443. upper = current;
  444. }
  445. }
  446. return lower;
  447. }
  448. /// <summary>
  449. /// <value>true</value> if the time is within a leap year, <value>false</value> otherwise
  450. /// </summary>
  451. public static double InLeapYear(double t)
  452. {
  453. var daysInYear = DaysInYear(YearFromTime(t));
  454. if (daysInYear.Equals(365))
  455. {
  456. return 0;
  457. }
  458. if (daysInYear.Equals(366))
  459. {
  460. return 1;
  461. }
  462. throw new ArgumentException();
  463. }
  464. /// <summary>
  465. /// The month number of a time value.
  466. /// </summary>
  467. public static double MonthFromTime(double t)
  468. {
  469. var dayWithinYear = DayWithinYear(t);
  470. var inLeapYear = InLeapYear(t);
  471. if (dayWithinYear < 31)
  472. {
  473. return 0;
  474. }
  475. if (dayWithinYear < 59 + inLeapYear)
  476. {
  477. return 1;
  478. }
  479. if (dayWithinYear < 90 + inLeapYear)
  480. {
  481. return 2;
  482. }
  483. if (dayWithinYear < 120 + inLeapYear)
  484. {
  485. return 3;
  486. }
  487. if (dayWithinYear < 151 + inLeapYear)
  488. {
  489. return 4;
  490. }
  491. if (dayWithinYear < 181 + inLeapYear)
  492. {
  493. return 5;
  494. }
  495. if (dayWithinYear < 212 + inLeapYear)
  496. {
  497. return 6;
  498. }
  499. if (dayWithinYear < 243 + inLeapYear)
  500. {
  501. return 7;
  502. }
  503. if (dayWithinYear < 273 + inLeapYear)
  504. {
  505. return 8;
  506. }
  507. if (dayWithinYear < 304 + inLeapYear)
  508. {
  509. return 9;
  510. }
  511. if (dayWithinYear < 334 + inLeapYear)
  512. {
  513. return 10;
  514. }
  515. if (dayWithinYear < 365 + inLeapYear)
  516. {
  517. return 11;
  518. }
  519. throw new InvalidOperationException();
  520. }
  521. public static double DayWithinYear(double t)
  522. {
  523. return Day(t) - DayFromYear(YearFromTime(t));
  524. }
  525. public static double DateFromTime(double t)
  526. {
  527. var monthFromTime = MonthFromTime(t);
  528. var dayWithinYear = DayWithinYear(t);
  529. if (monthFromTime.Equals(0))
  530. {
  531. return dayWithinYear + 1;
  532. }
  533. if (monthFromTime.Equals(1))
  534. {
  535. return dayWithinYear - 30;
  536. }
  537. if (monthFromTime.Equals(2))
  538. {
  539. return dayWithinYear - 58;
  540. }
  541. if (monthFromTime.Equals(3))
  542. {
  543. return dayWithinYear - 89;
  544. }
  545. if (monthFromTime.Equals(4))
  546. {
  547. return dayWithinYear - 119;
  548. }
  549. if (monthFromTime.Equals(5))
  550. {
  551. return dayWithinYear - 150;
  552. }
  553. if (monthFromTime.Equals(6))
  554. {
  555. return dayWithinYear - 180;
  556. }
  557. if (monthFromTime.Equals(7))
  558. {
  559. return dayWithinYear - 211;
  560. }
  561. if (monthFromTime.Equals(8))
  562. {
  563. return dayWithinYear - 242;
  564. }
  565. if (monthFromTime.Equals(9))
  566. {
  567. return dayWithinYear - 272;
  568. }
  569. if (monthFromTime.Equals(10))
  570. {
  571. return dayWithinYear - 303;
  572. }
  573. if (monthFromTime.Equals(11))
  574. {
  575. return dayWithinYear - 333;
  576. }
  577. throw new InvalidOperationException();
  578. }
  579. /// <summary>
  580. /// The weekday for a particular time value.
  581. /// </summary>
  582. public static double WeekDay(double t)
  583. {
  584. return (Day(t) + 4)%7;
  585. }
  586. public static double LocalTza
  587. {
  588. get
  589. {
  590. return TimeZoneInfo.Local.BaseUtcOffset.TotalMilliseconds;
  591. }
  592. }
  593. public static double DaylightSavingTa(double t)
  594. {
  595. var timeInYear = t - TimeFromYear(YearFromTime(t));
  596. var isLeapYear = InLeapYear(t).Equals(1);
  597. var weekDay = WeekDay(TimeFromYear(YearFromTime(t)));
  598. var year = YearFromTime(t);
  599. if (year < 9999 && year > -9999)
  600. {
  601. // in DateTimeOffset range so we can use it
  602. }
  603. else
  604. {
  605. // use similar leap-ed year
  606. year = isLeapYear ? 2000 : 1999;
  607. }
  608. var dateTime = new DateTime((int)year, 1, 1).AddMilliseconds(timeInYear);
  609. return TimeZoneInfo.Local.IsDaylightSavingTime(dateTime) ? MsPerHour : 0;
  610. }
  611. public static double UtcToLocalTime(double t)
  612. {
  613. return t + LocalTza + DaylightSavingTa(t);
  614. }
  615. public static double LocalTimeToUtc(double t)
  616. {
  617. return t - LocalTza - DaylightSavingTa(t - LocalTza);
  618. }
  619. }
  620. }