1 module libwasm.moment;
2 
3 import libwasm.types;
4 import libwasm.lodash;
5 
6 import std.traits;
7 
8 nothrow:
9 @safe:
10 Moment moment() {
11     return Moment().initArgs(Eval("undefined")); // now
12 }
13 
14 Moment momentHandle(Handle handle) {
15     return Moment().initHandle(handle);
16 }
17 Moment momentHandle(T)(ref T handle) if (is(T : JsHandle)) {
18     return Moment().initHandle(handle.handle);
19 }
20 
21 Moment moment(ARGS...)(auto ref ARGS args) if (ARGS.length > 0) {
22     return Moment().initArgs(args);
23 }
24 
25 struct Moment {
26     private Lodash m_ld;
27     private Handle m_saved;
28     private bool m_dirty;
29 nothrow:
30 @safe:
31     private Moment initHandle(Handle h) {
32         m_ld = Lodash(h, VarType.handle, 1024);
33         return this;
34     }
35 
36     private Moment initArgs(ARGS...)(auto ref ARGS args)
37     {
38         m_ld = Lodash();
39         m_ld.defaultTo(Eval("moment"));
40         m_ld.attempt(args);
41         return this;
42     }
43      
44     Handle save()(bool drop_previous = true) {
45         if (m_saved && !m_dirty) return m_saved;
46         scope(exit) m_dirty = false;
47         if (m_saved && drop_previous) dropHandle!Handle(m_saved);
48         m_saved = m_ld.execute!Handle();
49         m_ld = Lodash(m_saved, VarType.handle, 1024);
50         
51         return m_saved;
52     }
53     
54 
55 
56     private void reload() {
57         m_ld = Lodash(m_saved, VarType.handle, 1024);
58     }
59 
60     auto ref duration()() {
61         m_dirty = true;
62         save(); scope(exit) reload();
63         m_ld.invoke("duration", fmt);
64         return this;
65     }
66 
67     string format()(string fmt = null) {
68         save(); scope(exit) reload();
69         m_ld.invoke("format", fmt);
70         return m_ld.execute!string();
71     }
72 
73     auto ref utc()(bool keepLocalTime = null) {
74         m_dirty = true;
75         m_ld.invoke("utc", keepLocalTime);
76         return this;
77     }
78     auto ref startOf()(T val) {
79         m_dirty = true;
80         m_ld.invoke("startOf", val);
81         return this;
82     }
83 
84     auto ref endOf()(T val) {
85         m_dirty = true;
86         m_ld.invoke("endOf", val);
87         return this;
88     }
89     
90     bool isUtc(ARGS...)(auto ref ARGS args) {
91         m_ld.invoke("isUtc", args);
92         m_ld.toLength();
93         return m_ld.execute!long() > 0;
94     }
95 
96     long unix() {
97         save(); scope(exit) reload();
98         m_ld.invoke("unix");
99         return m_ld.execute!long();
100     }
101     auto ref add(ARGS...)(auto ref ARGS args) {
102         m_dirty = true;
103         m_ld.invoke("add", args);
104         return this;
105     }
106     auto ref substract(ARGS...)(auto ref ARGS args) {
107         m_dirty = true;
108         m_ld.invoke("substract", args);
109         return this;
110     }
111 
112     auto ref diff(ARGS...)(auto ref ARGS args) {
113         m_dirty = true;
114         m_ld.invoke("diff", args);
115         return this;
116     }
117 
118     string humanize(ARGS...)(auto ref ARGS args) {
119         save(); scope(exit) reload();
120         m_ld.invoke("humanize", args);
121         return m_ld.execute!string();
122     }
123 
124 
125 
126     long valueOf()() {
127         save(); scope(exit) reload();
128         m_ld.invoke("valueOf");
129         return m_ld.execute!long();
130     }
131 
132     long year()() {
133         save(); scope(exit) reload();
134         m_ld.invoke("year");
135         return m_ld.execute!long();
136     }
137 
138     auto ref year(T)(T val) if (isNumeric!T || isSomeString!T)
139     {
140         m_dirty = true;
141         m_ld.invoke("year", val);
142         return this;
143     }
144 
145     long years()() {
146         save(); scope(exit) reload();
147         m_ld.invoke("years");
148         return m_ld.execute!long();
149     }
150 
151     auto ref years(T)(T val) if (isNumeric!T || isSomeString!T)
152     {
153         m_dirty = true;
154         m_ld.invoke("year", val);
155         return this;
156     }
157 
158 
159     long month()() {
160         save(); scope(exit) reload();
161         m_ld.invoke("month");
162         return m_ld.execute!long();
163     }
164     
165     auto ref month(T)(T val) if (isNumeric!T || isSomeString!T)
166     {
167         m_dirty = true;
168         m_ld.invoke("month", val);
169         return this;
170     }
171 
172     long months()() {
173         save(); scope(exit) reload();
174         m_ld.invoke("months");
175         return m_ld.execute!long();
176     }
177 
178     auto ref months(T)(T val) if (isNumeric!T || isSomeString!T)
179     {
180         m_dirty = true;
181         m_ld.invoke("months", val);
182         return this;
183     }
184 
185     long quarter()() {
186         save(); scope(exit) reload();
187         m_ld.invoke("quarter");
188         return m_ld.execute!long();
189     }
190 
191     auto ref quarter(T)(T val) if (isNumeric!T || isSomeString!T)
192     {
193         m_dirty = true;
194         m_ld.invoke("quarter", val);
195         return this;
196     }
197     
198     long quarters()() {
199         save(); scope(exit) reload();
200         m_ld.invoke("quarters");
201         return m_ld.execute!long();
202     }
203     auto ref quarters(T)(T val) if (isNumeric!T || isSomeString!T)
204     {
205         m_dirty = true;
206         m_ld.invoke("quarters", val);
207         return this;
208     }
209     
210     long day()() {
211         save(); scope(exit) reload();
212         m_ld.invoke("day");
213         return m_ld.execute!long();
214     }
215     auto ref day(T)(T val) if (isNumeric!T || isSomeString!T)
216     {
217         m_dirty = true;
218         m_ld.invoke("day", val);
219         return this;
220     }
221     long days()() {
222         save(); scope(exit) reload();
223         m_ld.invoke("days");
224         return m_ld.execute!long();
225     }
226     auto ref days(T)(T val) if (isNumeric!T || isSomeString!T)
227     {
228         m_dirty = true;
229         m_ld.invoke("days", val);
230         return this;
231     }
232     
233     long date()() {
234         save(); scope(exit) reload();
235         m_ld.invoke("date");
236         return m_ld.execute!long();
237     }
238     auto ref date(T)(T val) if (isNumeric!T || isSomeString!T)
239     {
240         m_dirty = true;
241         m_ld.invoke("date", val);
242         return this;
243     }
244     
245     long dates()() {
246         save(); scope(exit) reload();
247         m_ld.invoke("dates");
248         return m_ld.execute!long();
249     }
250     auto ref dates(T)(T val) if (isNumeric!T || isSomeString!T)
251     {
252         m_dirty = true;
253         m_ld.invoke("dates", val);
254         return this;
255     }
256     
257     long hour()() {
258         save(); scope(exit) reload();
259         m_ld.invoke("hour");
260         return m_ld.execute!long();
261     }
262     auto ref hour(T)(T val) if (isNumeric!T || isSomeString!T)
263     {
264         m_dirty = true;
265         m_ld.invoke("hour", val);
266         return this;
267     }
268 
269     long hours()() {
270         save(); scope(exit) reload();
271         m_ld.invoke("hours");
272         return m_ld.execute!long();
273     }
274     auto ref hours(T)(T val) if (isNumeric!T || isSomeString!T)
275     {
276         m_dirty = true;
277         m_ld.invoke("hours", val);
278         return this;
279     }
280     long second()() {
281         save(); scope(exit) reload();
282         m_ld.invoke("second");
283         return m_ld.execute!long();
284     }
285     auto ref second(T)(T val) if (isNumeric!T || isSomeString!T)
286     {
287         m_dirty = true;
288         m_ld.invoke("second", val);
289         return this;
290     }
291     long seconds()() {
292         save(); scope(exit) reload();
293         m_ld.invoke("seconds");
294         return m_ld.execute!long();
295     }
296     auto ref seconds(T)(T val) if (isNumeric!T || isSomeString!T)
297     {
298         m_dirty = true;
299         m_ld.invoke("seconds", val);
300         return this;
301     }
302     long minute()() {
303         save(); scope(exit) reload();
304         m_ld.invoke("minute");
305         return m_ld.execute!long();
306     }
307     auto ref minute(T)(T val) if (isNumeric!T || isSomeString!T)
308     {
309         m_dirty = true;
310         m_ld.invoke("minute", val);
311         return this;
312     }
313     long minutes()() {
314         save(); scope(exit) reload();
315         m_ld.invoke("minutes");
316         return m_ld.execute!long();
317     }
318     auto ref minutes(T)(T val) if (isNumeric!T || isSomeString!T)
319     {
320         m_dirty = true;
321         m_ld.invoke("minutes", val);
322         return this;
323     }
324     long milliseconds()() {
325         save(); scope(exit) reload();
326         m_ld.invoke("milliseconds");
327         return m_ld.execute!long();
328     }
329     auto ref milliseconds(T)(T val) if (isNumeric!T || isSomeString!T)
330     {
331         m_dirty = true;
332         m_ld.invoke("milliseconds", val);
333         return this;
334     }
335     long millisecond()() {
336         save(); scope(exit) reload();
337         m_ld.invoke("millisecond");
338         return m_ld.execute!long();
339     }
340     auto ref millisecond(T)(T val) if (isNumeric!T || isSomeString!T)
341     {
342         m_dirty = true;
343         m_ld.invoke("millisecond", val);
344         return this;
345     }
346     long weekday()() {
347         save(); scope(exit) reload();
348         m_ld.invoke("weekday");
349         return m_ld.execute!long();
350     }
351     auto ref weekday(T)(T val) if (isNumeric!T || isSomeString!T)
352     {
353         m_dirty = true;
354         m_ld.invoke("weekday", val);
355         return this;
356     }
357     long isoWeekday()() {
358         save(); scope(exit) reload();
359         m_ld.invoke("isoWeekday");
360         return m_ld.execute!long();
361     }
362     auto ref isoWeekday(T)(T val) if (isNumeric!T || isSomeString!T)
363     {
364         m_dirty = true;
365         m_ld.invoke("isoWeekday", val);
366         return this;
367     }
368     long weekYear()() {
369         save(); scope(exit) reload();
370         m_ld.invoke("weekYear");
371         return m_ld.execute!long();
372     }
373     auto ref weekYear(T)(T val) if (isNumeric!T || isSomeString!T)
374     {
375         m_dirty = true;
376         m_ld.invoke("weekYear", val);
377         return this;
378     }
379     
380     long isoWeekYear()() {
381         save(); scope(exit) reload();
382         m_ld.invoke("isoWeekYear");
383         return m_ld.execute!long();
384     }
385     auto ref isoWeekYear(T)(T val) if (isNumeric!T || isSomeString!T)
386     {
387         m_dirty = true;
388         m_ld.invoke("isoWeekYear", val);
389         return this;
390     }
391 
392     long weeks()() {
393         save(); scope(exit) reload();
394         m_ld.invoke("weeks");
395         return m_ld.execute!long();
396     }
397     auto ref weeks(T)(T val) if (isNumeric!T || isSomeString!T)
398     {
399         m_dirty = true;
400         m_ld.invoke("weeks", val);
401         return this;
402     }
403     
404     long week()() {
405         save(); scope(exit) reload();
406         m_ld.invoke("week");
407         return m_ld.execute!long();
408     }
409     auto ref week(T)(T val) if (isNumeric!T || isSomeString!T)
410     {
411         m_dirty = true;
412         m_ld.invoke("week", val);
413         return this;
414     }
415     long isoWeek()() {
416         save(); scope(exit) reload();
417         m_ld.invoke("isoWeek");
418         return m_ld.execute!long();
419     }
420     auto ref isoWeek(T)(T val) if (isNumeric!T || isSomeString!T)
421     {
422         m_dirty = true;
423         m_ld.invoke("isoWeek", val);
424         return this;
425     }
426 
427     long isoWeeks()() {
428         save(); scope(exit) reload();
429         m_ld.invoke("isoWeeks");
430         return m_ld.execute!long();
431     }
432     auto ref isoWeeks(T)(T val) if (isNumeric!T || isSomeString!T)
433     {
434         m_dirty = true;
435         m_ld.invoke("isoWeeks", val);
436         return this;
437     }
438 
439     long weeksInYear()() {
440         save(); scope(exit) reload();
441         m_ld.invoke("weeksInYear");
442         return m_ld.execute!long();
443     }
444     
445     long isoWeeksInYear()() {
446         save(); scope(exit) reload();
447         m_ld.invoke("isoWeeksInYear");
448         return m_ld.execute!long();
449     }
450     long isoWeeksInISOWeekYear()() {
451         save(); scope(exit) reload();
452         m_ld.invoke("isoWeeksInISOWeekYear");
453         return m_ld.execute!long();
454     }
455     
456     long dayOfYear()() {
457         save(); scope(exit) reload();
458         m_ld.invoke("dayOfYear");
459         return m_ld.execute!long();
460     }
461     auto ref dayOfYear(T)(T val) if (isNumeric!T || isSomeString!T)
462     {
463         m_dirty = true;
464         m_ld.invoke("dayOfYear", val);
465         return this;
466     }
467         
468     long utcOffset()() {
469         save(); scope(exit) reload();
470         m_ld.invoke("utcOffset");
471         return m_ld.execute!long();
472     }
473 
474     auto ref abs()() {
475         m_dirty = true;
476         m_ld.invoke("abs");
477         return this;
478     }
479     auto ref utcOffset(T)(T val, bool keepLocalTime = true) if (isNumeric!T || isSomeString!T)
480     {
481         m_dirty = true;
482         m_ld.invoke("utcOffset", val, keepLocalTime);
483         return this;
484     }
485         
486     bool isUtcOffset()() {
487         save(); scope(exit) reload();
488         m_ld.invoke("isUtcOffset");
489         m_ld.toLength();
490         return m_ld.execute!long() > 0;
491     }
492     long daysInMonth()() {
493         save(); scope(exit) reload();
494         m_ld.invoke("daysInMonth");
495         return m_ld.execute!long();
496     }
497     bool isDST()() {
498         save(); scope(exit) reload();
499         m_ld.invoke("isDST");
500         m_ld.toLength();
501         return m_ld.execute!long() > 0;
502     }
503         
504     bool isValid()() {
505         save(); scope(exit) reload();
506         m_ld.invoke("isValid");
507         m_ld.toLength();
508         return m_ld.execute!long() > 0;
509     }
510     long invalidAt() {
511         save(); scope(exit) reload();
512         m_ld.invoke("invalidAt");
513         return m_ld.execute!long();
514     }
515     string toJSON()() {
516         save(); scope(exit) reload();
517         m_ld.invoke("toJSON");
518         return m_ld.execute!string();
519     }
520 
521     string toISOString()() {
522         save(); scope(exit) reload();
523         m_ld.invoke("toISOString");
524         return m_ld.execute!string();
525     }
526 
527 
528     string fromNow()(bool without_suffix) {
529         save(); scope(exit) reload();
530         m_ld.invoke("fromNow", without_suffix);
531         return m_ld.execute!string();
532     }
533     string toNow()(bool without_prefix) {
534         save(); scope(exit) reload();
535         m_ld.invoke("fromNow", without_prefix);
536         return m_ld.execute!string();
537     }
538     
539     string from(ARGS...)(auto ref ARGS args) {
540         save(); scope(exit) reload();
541         m_ld.invoke("from", args);
542         return m_ld.execute!string();
543     }
544     string to(ARGS...)(auto ref ARGS args) {
545         save(); scope(exit) reload();
546         m_ld.invoke("to", args);
547         return m_ld.execute!string();
548     }
549     bool isLeapYear(ARGS...)(auto ref ARGS args) {
550         save(); scope(exit) reload();
551         m_ld.invoke("isLeapYear", args);
552         m_ld.toLength();
553         return m_ld.execute!long() > 0;
554     }
555 
556     string zoneAbbr()() {
557         save(); scope(exit) reload();
558         m_ld.invoke("zoneAbbr");
559         return m_ld.execute!string();
560     }
561     string zoneName()() {
562         save(); scope(exit) reload();
563         m_ld.invoke("zoneAbbr");
564         return m_ld.execute!string();
565     }
566     
567     
568     bool isBefore(ARGS...)(auto ref ARGS args) {
569         save(); scope(exit) reload();
570         m_ld.invoke("isBefore", args);
571         m_ld.toLength();
572         return m_ld.execute!long() > 0;
573     }
574     bool isAfter(ARGS...)(auto ref ARGS args) {
575         save(); scope(exit) reload();
576         m_ld.invoke("isAfter", args);
577         m_ld.toLength();
578         return m_ld.execute!long() > 0;
579     }
580     bool isSame(ARGS...)(auto ref ARGS args) {
581         save(); scope(exit) reload();
582         m_ld.invoke("isSame", args);
583         m_ld.toLength();
584         return m_ld.execute!long() > 0;
585     }
586     bool isSameOrAfter(ARGS...)(auto ref ARGS args) {
587         save(); scope(exit) reload();
588         m_ld.invoke("isSameOrAfter", args);
589         m_ld.toLength();
590         return m_ld.execute!long() > 0;
591     }
592     bool isSameOrBefore(ARGS...)(auto ref ARGS args) {
593         save(); scope(exit) reload();
594         m_ld.invoke("isSameOrBefore", args);
595         m_ld.toLength();
596         return m_ld.execute!long() > 0;
597     }
598     bool isBetween(ARGS...)(auto ref ARGS args) {
599         save(); scope(exit) reload();
600         m_ld.invoke("isBetween", args);
601         m_ld.toLength();
602         return m_ld.execute!long() > 0;
603     }
604 
605 
606     string locale()() {
607         save(); scope(exit) reload();
608         m_ld.invoke("locale");
609         return m_ld.execute!string();
610     }    
611     string locale(ARGS...)(auto ref ARGS args) {
612         save(); scope(exit) reload();
613         m_ld.invoke("locale", args);
614         return m_ld.execute!string();
615     }
616 
617     double asMilliseconds()() {
618         save(); scope(exit) reload();
619         m_ld.invoke("asMilliseconds");
620         return m_ld.execute!double();
621     }
622     double asSeconds()() {
623         save(); scope(exit) reload();
624         m_ld.invoke("asSeconds");
625         return m_ld.execute!double();
626     }
627     double asMinutes()() {
628         save(); scope(exit) reload();
629         m_ld.invoke("asMinutes");
630         return m_ld.execute!double();
631     }
632     double asHours()() {
633         save(); scope(exit) reload();
634         m_ld.invoke("asHours");
635         return m_ld.execute!double();
636     }
637     double asDays()() {
638         save(); scope(exit) reload();
639         m_ld.invoke("asDays");
640         return m_ld.execute!double();
641     }
642     double asWeeks()() {
643         save(); scope(exit) reload();
644         m_ld.invoke("asWeeks");
645         return m_ld.execute!double();
646     }
647     double asMonths()() {
648         save(); scope(exit) reload();
649         m_ld.invoke("asMonths");
650         return m_ld.execute!double();
651     }
652     double asYears()() {
653         save(); scope(exit) reload();
654         m_ld.invoke("asYears");
655         return m_ld.execute!double();
656     }
657 }