1 
2 
3 /*****************************************************************************/
4 /*                                                                           */
5 /*    Copyright (c) 1995 - 2015 by Steffen Beyer.                            */
6 /*    All rights reserved.                                                   */
7 /*                                                                           */
8 /*    This package is free software; you can redistribute it                 */
9 /*    and/or modify it under the same terms as Perl itself.                  */
10 /*                                                                           */
11 /*****************************************************************************/
12 
13 
14 #include "EXTERN.h"
15 #include "perl.h"
16 #include "XSUB.h"
17 
18 
19 #include "patchlevel.h"
20 #if ((PATCHLEVEL < 4) || ((PATCHLEVEL == 4) && (SUBVERSION < 5)))
21 /* PL_na was introduced in perl5.004_05 */
22 #ifndef PL_na
23     #define PL_na na
24 #endif
25 #endif
26 #if (PATCHLEVEL < 4)
27 /* GIMME_V was introduced in perl5.004 */
28 #ifndef GIMME_V
29     #define GIMME_V GIMME
30 #endif
31 #endif
32 
33 
34 #include "DateCalc.h"
35 
36 
37 const char *_DateCalc_DATE_ERROR       = "not a valid date";
38 const char *_DateCalc_TIME_ERROR       = "not a valid time";
39 const char *_DateCalc_YEAR_ERROR       = "year out of range";
40 const char *_DateCalc_MONTH_ERROR      = "month out of range";
41 const char *_DateCalc_WEEK_ERROR       = "week out of range";
42 const char *_DateCalc_DAYOFWEEK_ERROR  = "day of week out of range";
43 const char *_DateCalc_DATE_RANGE_ERROR = "date out of range";
44 const char *_DateCalc_TIME_RANGE_ERROR = "time out of range";
45 const char *_DateCalc_FACTOR_ERROR     = "factor out of range";
46 const char *_DateCalc_LANGUAGE_ERROR   = "language not available";
47 const char *_DateCalc_SYSTEM_ERROR     = "not available on this system";
48 const char *_DateCalc_MEMORY_ERROR     = "unable to allocate memory";
49 const char *_DateCalc_STRING_ERROR     = "argument is not a string";
50 const char *_DateCalc_SCALAR_ERROR     = "argument is not a scalar";
51 
52 
53 #define DATECALC_STRING(ref,var,len) \
54     ( ref && !(SvROK(ref)) && SvPOK(ref) && \
55     (var = (charptr)SvPV(ref,PL_na)) && \
56     ((len = (N_int)SvCUR(ref)) | 1) )
57 
58 #define DATECALC_SCALAR(ref,typ,var) \
59     ( ref && !(SvROK(ref)) && ((var = (typ)SvIV(ref)) | 1) )
60 
61 
62 #define DATECALC_ERROR(message) \
63     croak("Date::Calc::%s(): %s", GvNAME(CvGV(cv)), message)
64 
65 
66 #define DATECALC_DATE_ERROR \
67     DATECALC_ERROR( _DateCalc_DATE_ERROR )
68 
69 #define DATECALC_TIME_ERROR \
70     DATECALC_ERROR( _DateCalc_TIME_ERROR )
71 
72 #define DATECALC_YEAR_ERROR \
73     DATECALC_ERROR( _DateCalc_YEAR_ERROR )
74 
75 #define DATECALC_MONTH_ERROR \
76     DATECALC_ERROR( _DateCalc_MONTH_ERROR )
77 
78 #define DATECALC_WEEK_ERROR \
79     DATECALC_ERROR( _DateCalc_WEEK_ERROR )
80 
81 #define DATECALC_DAYOFWEEK_ERROR \
82     DATECALC_ERROR( _DateCalc_DAYOFWEEK_ERROR )
83 
84 #define DATECALC_DATE_RANGE_ERROR \
85     DATECALC_ERROR( _DateCalc_DATE_RANGE_ERROR )
86 
87 #define DATECALC_TIME_RANGE_ERROR \
88     DATECALC_ERROR( _DateCalc_TIME_RANGE_ERROR )
89 
90 #define DATECALC_FACTOR_ERROR \
91     DATECALC_ERROR( _DateCalc_FACTOR_ERROR )
92 
93 #define DATECALC_LANGUAGE_ERROR \
94     DATECALC_ERROR( _DateCalc_LANGUAGE_ERROR )
95 
96 #define DATECALC_SYSTEM_ERROR \
97     DATECALC_ERROR( _DateCalc_SYSTEM_ERROR )
98 
99 #define DATECALC_MEMORY_ERROR \
100     DATECALC_ERROR( _DateCalc_MEMORY_ERROR )
101 
102 #define DATECALC_STRING_ERROR \
103     DATECALC_ERROR( _DateCalc_STRING_ERROR )
104 
105 #define DATECALC_SCALAR_ERROR \
106     DATECALC_ERROR( _DateCalc_SCALAR_ERROR )
107 
108 
109 MODULE = Date::Calc::XS		PACKAGE = Date::Calc::XS		PREFIX = DateCalc_
110 
111 
112 PROTOTYPES: DISABLE
113 
114 
115 void
DateCalc_Days_in_Year(year,month)116 DateCalc_Days_in_Year(year,month)
117     Z_int	year
118     Z_int	month
119 PPCODE:
120 {
121     if (year > 0)
122     {
123         if ((month >= 1) and (month <= 12))
124         {
125             EXTEND(sp,1);
126             PUSHs(sv_2mortal(newSViv((IV)DateCalc_Days_in_Year_[DateCalc_leap_year(year)][month+1])));
127         }
128         else DATECALC_MONTH_ERROR;
129     }
130     else DATECALC_YEAR_ERROR;
131 }
132 
133 
134 void
DateCalc_Days_in_Month(year,month)135 DateCalc_Days_in_Month(year,month)
136     Z_int	year
137     Z_int	month
138 PPCODE:
139 {
140     if (year > 0)
141     {
142         if ((month >= 1) and (month <= 12))
143         {
144             EXTEND(sp,1);
145             PUSHs(sv_2mortal(newSViv((IV)DateCalc_Days_in_Month_[DateCalc_leap_year(year)][month])));
146         }
147         else DATECALC_MONTH_ERROR;
148     }
149     else DATECALC_YEAR_ERROR;
150 }
151 
152 
153 Z_int
DateCalc_Weeks_in_Year(year)154 DateCalc_Weeks_in_Year(year)
155     Z_int	year
156 CODE:
157 {
158     if (year > 0)
159     {
160         RETVAL = DateCalc_Weeks_in_Year(year);
161     }
162     else DATECALC_YEAR_ERROR;
163 }
164 OUTPUT:
165 RETVAL
166 
167 
168 boolean
DateCalc_leap_year(year)169 DateCalc_leap_year(year)
170     Z_int	year
171 CODE:
172 {
173     if (year > 0)
174     {
175         RETVAL = DateCalc_leap_year(year);
176     }
177     else DATECALC_YEAR_ERROR;
178 }
179 OUTPUT:
180 RETVAL
181 
182 
183 boolean
DateCalc_check_date(year,month,day)184 DateCalc_check_date(year,month,day)
185     Z_int	year
186     Z_int	month
187     Z_int	day
188 
189 
190 boolean
191 DateCalc_check_time(hour,min,sec)
192     Z_int	hour
193     Z_int	min
194     Z_int	sec
195 
196 
197 boolean
198 DateCalc_check_business_date(year,week,dow)
199     Z_int	year
200     Z_int	week
201     Z_int	dow
202 
203 
204 Z_int
205 DateCalc_Day_of_Year(year,month,day)
206     Z_int	year
207     Z_int	month
208     Z_int	day
209 CODE:
210 {
211     RETVAL = DateCalc_Day_of_Year(year,month,day);
212     if (RETVAL == 0) DATECALC_DATE_ERROR;
213 }
214 OUTPUT:
215 RETVAL
216 
217 
218 Z_long
DateCalc_Date_to_Days(year,month,day)219 DateCalc_Date_to_Days(year,month,day)
220     Z_int	year
221     Z_int	month
222     Z_int	day
223 CODE:
224 {
225     RETVAL = DateCalc_Date_to_Days(year,month,day);
226     if (RETVAL == 0) DATECALC_DATE_ERROR;
227 }
228 OUTPUT:
229 RETVAL
230 
231 
232 Z_int
DateCalc_Day_of_Week(year,month,day)233 DateCalc_Day_of_Week(year,month,day)
234     Z_int	year
235     Z_int	month
236     Z_int	day
237 CODE:
238 {
239     RETVAL = DateCalc_Day_of_Week(year,month,day);
240     if (RETVAL == 0) DATECALC_DATE_ERROR;
241 }
242 OUTPUT:
243 RETVAL
244 
245 
246 Z_int
DateCalc_Week_Number(year,month,day)247 DateCalc_Week_Number(year,month,day)
248     Z_int	year
249     Z_int	month
250     Z_int	day
251 CODE:
252 {
253     if (DateCalc_check_date(year,month,day))
254     {
255         RETVAL = DateCalc_Week_Number(year,month,day);
256     }
257     else DATECALC_DATE_ERROR;
258 }
259 OUTPUT:
260 RETVAL
261 
262 
263 void
DateCalc_Week_of_Year(year,month,day)264 DateCalc_Week_of_Year(year,month,day)
265     Z_int	year
266     Z_int	month
267     Z_int	day
268 PPCODE:
269 {
270     Z_int week;
271 
272     if (DateCalc_week_of_year(&week,&year,month,day))
273     {
274         if (GIMME_V == G_ARRAY)
275         {
276             EXTEND(sp,2);
277             PUSHs(sv_2mortal(newSViv((IV)week)));
278             PUSHs(sv_2mortal(newSViv((IV)year)));
279         }
280         else
281         {
282             EXTEND(sp,1);
283             PUSHs(sv_2mortal(newSViv((IV)week)));
284         }
285     }
286     else DATECALC_DATE_ERROR;
287 }
288 
289 
290 void
DateCalc_Monday_of_Week(week,year)291 DateCalc_Monday_of_Week(week,year)
292     Z_int	week
293     Z_int	year
294 PPCODE:
295 {
296     Z_int month;
297     Z_int day;
298 
299     if (year > 0)
300     {
301         if ((week > 0) and (week <= DateCalc_Weeks_in_Year(year)))
302         {
303             if (DateCalc_monday_of_week(week,&year,&month,&day))
304             {
305                 EXTEND(sp,3);
306                 PUSHs(sv_2mortal(newSViv((IV)year)));
307                 PUSHs(sv_2mortal(newSViv((IV)month)));
308                 PUSHs(sv_2mortal(newSViv((IV)day)));
309             }
310             else DATECALC_DATE_ERROR;
311         }
312         else DATECALC_WEEK_ERROR;
313     }
314     else DATECALC_YEAR_ERROR;
315 }
316 
317 
318 void
DateCalc_Nth_Weekday_of_Month_Year(year,month,dow,n)319 DateCalc_Nth_Weekday_of_Month_Year(year,month,dow,n)
320     Z_int	year
321     Z_int	month
322     Z_int	dow
323     Z_int	n
324 PPCODE:
325 {
326     Z_int day;
327 
328     if (year > 0)
329     {
330         if ((month >= 1) and (month <= 12))
331         {
332             if ((dow >= 1) and (dow <= 7))
333             {
334                 if ((n >= 1) and (n <= 5))
335                 {
336                     if (DateCalc_nth_weekday_of_month_year(&year,&month,&day,dow,n))
337                     {
338                         EXTEND(sp,3);
339                         PUSHs(sv_2mortal(newSViv((IV)year)));
340                         PUSHs(sv_2mortal(newSViv((IV)month)));
341                         PUSHs(sv_2mortal(newSViv((IV)day)));
342                     }
343                     /* else return empty list */
344                 }
345                 else DATECALC_FACTOR_ERROR;
346             }
347             else DATECALC_DAYOFWEEK_ERROR;
348         }
349         else DATECALC_MONTH_ERROR;
350     }
351     else DATECALC_YEAR_ERROR;
352 }
353 
354 
355 void
DateCalc_Standard_to_Business(year,month,day)356 DateCalc_Standard_to_Business(year,month,day)
357     Z_int	year
358     Z_int	month
359     Z_int	day
360 PPCODE:
361 {
362     Z_int week;
363     Z_int dow;
364 
365     if (DateCalc_standard_to_business(&year,&week,&dow,month,day))
366     {
367         EXTEND(sp,3);
368         PUSHs(sv_2mortal(newSViv((IV)year)));
369         PUSHs(sv_2mortal(newSViv((IV)week)));
370         PUSHs(sv_2mortal(newSViv((IV)dow)));
371     }
372     else DATECALC_DATE_ERROR;
373 }
374 
375 
376 void
DateCalc_Business_to_Standard(year,week,dow)377 DateCalc_Business_to_Standard(year,week,dow)
378     Z_int	year
379     Z_int	week
380     Z_int	dow
381 PPCODE:
382 {
383     Z_int month;
384     Z_int day;
385 
386     if (DateCalc_business_to_standard(&year,&month,&day,week,dow))
387     {
388         EXTEND(sp,3);
389         PUSHs(sv_2mortal(newSViv((IV)year)));
390         PUSHs(sv_2mortal(newSViv((IV)month)));
391         PUSHs(sv_2mortal(newSViv((IV)day)));
392     }
393     else DATECALC_DATE_ERROR;
394 }
395 
396 
397 Z_long
DateCalc_Delta_Days(year1,month1,day1,year2,month2,day2)398 DateCalc_Delta_Days(year1,month1,day1, year2,month2,day2)
399     Z_int	year1
400     Z_int	month1
401     Z_int	day1
402     Z_int	year2
403     Z_int	month2
404     Z_int	day2
405 CODE:
406 {
407     if (DateCalc_check_date(year1,month1,day1) and
408         DateCalc_check_date(year2,month2,day2))
409     {
410         RETVAL = DateCalc_Delta_Days(year1,month1,day1, year2,month2,day2);
411     }
412     else DATECALC_DATE_ERROR;
413 }
414 OUTPUT:
415 RETVAL
416 
417 
418 void
DateCalc_Delta_DHMS(year1,month1,day1,hour1,min1,sec1,year2,month2,day2,hour2,min2,sec2)419 DateCalc_Delta_DHMS(year1,month1,day1, hour1,min1,sec1, year2,month2,day2, hour2,min2,sec2)
420     Z_int	year1
421     Z_int	month1
422     Z_int	day1
423     Z_int	hour1
424     Z_int	min1
425     Z_int	sec1
426     Z_int	year2
427     Z_int	month2
428     Z_int	day2
429     Z_int	hour2
430     Z_int	min2
431     Z_int	sec2
432 PPCODE:
433 {
434     Z_long Dd;
435     Z_int  Dh;
436     Z_int  Dm;
437     Z_int  Ds;
438 
439     if (DateCalc_check_date(year1,month1,day1) and
440         DateCalc_check_date(year2,month2,day2))
441     {
442         if (DateCalc_check_time(hour1,min1,sec1) and
443             DateCalc_check_time(hour2,min2,sec2))
444         {
445             if (DateCalc_delta_dhms(&Dd,&Dh,&Dm,&Ds,
446                                     year1,month1,day1, hour1,min1,sec1,
447                                     year2,month2,day2, hour2,min2,sec2))
448             {
449                 EXTEND(sp,4);
450                 PUSHs(sv_2mortal(newSViv((IV)Dd)));
451                 PUSHs(sv_2mortal(newSViv((IV)Dh)));
452                 PUSHs(sv_2mortal(newSViv((IV)Dm)));
453                 PUSHs(sv_2mortal(newSViv((IV)Ds)));
454             }
455             else DATECALC_DATE_ERROR;
456         }
457         else DATECALC_TIME_ERROR;
458     }
459     else DATECALC_DATE_ERROR;
460 }
461 
462 
463 void
DateCalc_Delta_YMD(year1,month1,day1,year2,month2,day2)464 DateCalc_Delta_YMD(year1,month1,day1, year2,month2,day2)
465     Z_int	year1
466     Z_int	month1
467     Z_int	day1
468     Z_int	year2
469     Z_int	month2
470     Z_int	day2
471 PPCODE:
472 {
473     if (DateCalc_delta_ymd(&year1,&month1,&day1, year2,month2,day2))
474     {
475         EXTEND(sp,3);
476         PUSHs(sv_2mortal(newSViv((IV)year1)));
477         PUSHs(sv_2mortal(newSViv((IV)month1)));
478         PUSHs(sv_2mortal(newSViv((IV)day1)));
479     }
480     else DATECALC_DATE_ERROR;
481 }
482 
483 
484 void
DateCalc_Delta_YMDHMS(year1,month1,day1,hour1,min1,sec1,year2,month2,day2,hour2,min2,sec2)485 DateCalc_Delta_YMDHMS(year1,month1,day1, hour1,min1,sec1, year2,month2,day2, hour2,min2,sec2)
486     Z_int	year1
487     Z_int	month1
488     Z_int	day1
489     Z_int	hour1
490     Z_int	min1
491     Z_int	sec1
492     Z_int	year2
493     Z_int	month2
494     Z_int	day2
495     Z_int	hour2
496     Z_int	min2
497     Z_int	sec2
498 PPCODE:
499 {
500     Z_int  D_y;
501     Z_int  D_m;
502     Z_int  D_d;
503     Z_int  Dh;
504     Z_int  Dm;
505     Z_int  Ds;
506 
507     if (DateCalc_check_date(year1,month1,day1) and
508         DateCalc_check_date(year2,month2,day2))
509     {
510         if (DateCalc_check_time(hour1,min1,sec1) and
511             DateCalc_check_time(hour2,min2,sec2))
512         {
513             if (DateCalc_delta_ymdhms(&D_y,&D_m,&D_d,    &Dh,&Dm,&Ds,
514                                       year1,month1,day1, hour1,min1,sec1,
515                                       year2,month2,day2, hour2,min2,sec2))
516             {
517                 EXTEND(sp,6);
518                 PUSHs(sv_2mortal(newSViv((IV)D_y)));
519                 PUSHs(sv_2mortal(newSViv((IV)D_m)));
520                 PUSHs(sv_2mortal(newSViv((IV)D_d)));
521                 PUSHs(sv_2mortal(newSViv((IV)Dh)));
522                 PUSHs(sv_2mortal(newSViv((IV)Dm)));
523                 PUSHs(sv_2mortal(newSViv((IV)Ds)));
524             }
525             else DATECALC_DATE_ERROR;
526         }
527         else DATECALC_TIME_ERROR;
528     }
529     else DATECALC_DATE_ERROR;
530 }
531 
532 
533 void
DateCalc_N_Delta_YMD(year1,month1,day1,year2,month2,day2)534 DateCalc_N_Delta_YMD(year1,month1,day1, year2,month2,day2)
535     Z_int	year1
536     Z_int	month1
537     Z_int	day1
538     Z_int	year2
539     Z_int	month2
540     Z_int	day2
541 PPCODE:
542 {
543     if (DateCalc_norm_delta_ymd(&year1,&month1,&day1, year2,month2,day2))
544     {
545         EXTEND(sp,3);
546         PUSHs(sv_2mortal(newSViv((IV)year1)));
547         PUSHs(sv_2mortal(newSViv((IV)month1)));
548         PUSHs(sv_2mortal(newSViv((IV)day1)));
549     }
550     else DATECALC_DATE_ERROR;
551 }
552 
553 
554 void
DateCalc_N_Delta_YMDHMS(year1,month1,day1,hour1,min1,sec1,year2,month2,day2,hour2,min2,sec2)555 DateCalc_N_Delta_YMDHMS(year1,month1,day1, hour1,min1,sec1, year2,month2,day2, hour2,min2,sec2)
556     Z_int	year1
557     Z_int	month1
558     Z_int	day1
559     Z_int	hour1
560     Z_int	min1
561     Z_int	sec1
562     Z_int	year2
563     Z_int	month2
564     Z_int	day2
565     Z_int	hour2
566     Z_int	min2
567     Z_int	sec2
568 PPCODE:
569 {
570     Z_int  D_y;
571     Z_int  D_m;
572     Z_int  D_d;
573     Z_int  Dhh;
574     Z_int  Dmm;
575     Z_int  Dss;
576 
577     if (DateCalc_check_date(year1,month1,day1) and
578         DateCalc_check_date(year2,month2,day2))
579     {
580         if (DateCalc_check_time(hour1,min1,sec1) and
581             DateCalc_check_time(hour2,min2,sec2))
582         {
583             if (DateCalc_norm_delta_ymdhms(&D_y,&D_m,&D_d,    &Dhh,&Dmm,&Dss,
584                                            year1,month1,day1, hour1,min1,sec1,
585                                            year2,month2,day2, hour2,min2,sec2))
586             {
587                 EXTEND(sp,6);
588                 PUSHs(sv_2mortal(newSViv((IV)D_y)));
589                 PUSHs(sv_2mortal(newSViv((IV)D_m)));
590                 PUSHs(sv_2mortal(newSViv((IV)D_d)));
591                 PUSHs(sv_2mortal(newSViv((IV)Dhh)));
592                 PUSHs(sv_2mortal(newSViv((IV)Dmm)));
593                 PUSHs(sv_2mortal(newSViv((IV)Dss)));
594             }
595             else DATECALC_DATE_ERROR;
596         }
597         else DATECALC_TIME_ERROR;
598     }
599     else DATECALC_DATE_ERROR;
600 }
601 
602 
603 void
DateCalc_Normalize_DHMS(Dd,Dh,Dm,Ds)604 DateCalc_Normalize_DHMS(Dd,Dh,Dm,Ds)
605     Z_long	Dd
606     Z_long	Dh
607     Z_long	Dm
608     Z_long	Ds
609 PPCODE:
610 {
611     DateCalc_Normalize_DHMS(&Dd,&Dh,&Dm,&Ds);
612     EXTEND(sp,4);
613     PUSHs(sv_2mortal(newSViv((IV)Dd)));
614     PUSHs(sv_2mortal(newSViv((IV)Dh)));
615     PUSHs(sv_2mortal(newSViv((IV)Dm)));
616     PUSHs(sv_2mortal(newSViv((IV)Ds)));
617 }
618 
619 
620 void
DateCalc_Add_Delta_Days(year,month,day,Dd)621 DateCalc_Add_Delta_Days(year,month,day, Dd)
622     Z_int	year
623     Z_int	month
624     Z_int	day
625     Z_long	Dd
626 PPCODE:
627 {
628     if (DateCalc_add_delta_days(&year,&month,&day, Dd))
629     {
630         EXTEND(sp,3);
631         PUSHs(sv_2mortal(newSViv((IV)year)));
632         PUSHs(sv_2mortal(newSViv((IV)month)));
633         PUSHs(sv_2mortal(newSViv((IV)day)));
634     }
635     else DATECALC_DATE_ERROR;
636 }
637 
638 
639 void
DateCalc_Add_Delta_DHMS(year,month,day,hour,min,sec,Dd,Dh,Dm,Ds)640 DateCalc_Add_Delta_DHMS(year,month,day, hour,min,sec, Dd,Dh,Dm,Ds)
641     Z_int	year
642     Z_int	month
643     Z_int	day
644     Z_int	hour
645     Z_int	min
646     Z_int	sec
647     Z_long	Dd
648     Z_long	Dh
649     Z_long	Dm
650     Z_long	Ds
651 PPCODE:
652 {
653     if (DateCalc_check_date(year,month,day))
654     {
655         if (DateCalc_check_time(hour,min,sec))
656         {
657             if (DateCalc_add_delta_dhms(&year,&month,&day,
658                                         &hour,&min,&sec,
659                                         Dd,Dh,Dm,Ds))
660             {
661                 EXTEND(sp,6);
662                 PUSHs(sv_2mortal(newSViv((IV)year)));
663                 PUSHs(sv_2mortal(newSViv((IV)month)));
664                 PUSHs(sv_2mortal(newSViv((IV)day)));
665                 PUSHs(sv_2mortal(newSViv((IV)hour)));
666                 PUSHs(sv_2mortal(newSViv((IV)min)));
667                 PUSHs(sv_2mortal(newSViv((IV)sec)));
668             }
669             else DATECALC_DATE_ERROR;
670         }
671         else DATECALC_TIME_ERROR;
672     }
673     else DATECALC_DATE_ERROR;
674 }
675 
676 
677 void
DateCalc_Add_Delta_YM(year,month,day,Dy,Dm)678 DateCalc_Add_Delta_YM(year,month,day, Dy,Dm)
679     Z_int	year
680     Z_int	month
681     Z_int	day
682     Z_long	Dy
683     Z_long	Dm
684 PPCODE:
685 {
686     if (DateCalc_add_delta_ym(&year,&month,&day, Dy,Dm))
687     {
688         EXTEND(sp,3);
689         PUSHs(sv_2mortal(newSViv((IV)year)));
690         PUSHs(sv_2mortal(newSViv((IV)month)));
691         PUSHs(sv_2mortal(newSViv((IV)day)));
692     }
693     else DATECALC_DATE_ERROR;
694 }
695 
696 
697 void
DateCalc_Add_Delta_YMD(year,month,day,Dy,Dm,Dd)698 DateCalc_Add_Delta_YMD(year,month,day, Dy,Dm,Dd)
699     Z_int	year
700     Z_int	month
701     Z_int	day
702     Z_long	Dy
703     Z_long	Dm
704     Z_long	Dd
705 PPCODE:
706 {
707     if (DateCalc_add_delta_ymd(&year,&month,&day, Dy,Dm,Dd))
708     {
709         EXTEND(sp,3);
710         PUSHs(sv_2mortal(newSViv((IV)year)));
711         PUSHs(sv_2mortal(newSViv((IV)month)));
712         PUSHs(sv_2mortal(newSViv((IV)day)));
713     }
714     else DATECALC_DATE_ERROR;
715 }
716 
717 
718 void
DateCalc_Add_Delta_YMDHMS(year,month,day,hour,min,sec,D_y,D_m,D_d,Dh,Dm,Ds)719 DateCalc_Add_Delta_YMDHMS(year,month,day, hour,min,sec, D_y,D_m,D_d, Dh,Dm,Ds)
720     Z_int	year
721     Z_int	month
722     Z_int	day
723     Z_int	hour
724     Z_int	min
725     Z_int	sec
726     Z_long	D_y
727     Z_long	D_m
728     Z_long	D_d
729     Z_long	Dh
730     Z_long	Dm
731     Z_long	Ds
732 PPCODE:
733 {
734     if (DateCalc_check_date(year,month,day))
735     {
736         if (DateCalc_check_time(hour,min,sec))
737         {
738             if (DateCalc_add_delta_ymdhms(&year,&month,&day,
739                                           &hour,&min,&sec,
740                                           D_y,D_m,D_d,
741                                           Dh,Dm,Ds))
742             {
743                 EXTEND(sp,6);
744                 PUSHs(sv_2mortal(newSViv((IV)year)));
745                 PUSHs(sv_2mortal(newSViv((IV)month)));
746                 PUSHs(sv_2mortal(newSViv((IV)day)));
747                 PUSHs(sv_2mortal(newSViv((IV)hour)));
748                 PUSHs(sv_2mortal(newSViv((IV)min)));
749                 PUSHs(sv_2mortal(newSViv((IV)sec)));
750             }
751             else DATECALC_DATE_ERROR;
752         }
753         else DATECALC_TIME_ERROR;
754     }
755     else DATECALC_DATE_ERROR;
756 }
757 
758 
759 void
DateCalc_Add_N_Delta_YMD(year,month,day,Dy,Dm,Dd)760 DateCalc_Add_N_Delta_YMD(year,month,day, Dy,Dm,Dd)
761     Z_int	year
762     Z_int	month
763     Z_int	day
764     Z_long	Dy
765     Z_long	Dm
766     Z_long	Dd
767 PPCODE:
768 {
769     if (DateCalc_add_norm_delta_ymd(&year,&month,&day, Dy,Dm,Dd))
770     {
771         EXTEND(sp,3);
772         PUSHs(sv_2mortal(newSViv((IV)year)));
773         PUSHs(sv_2mortal(newSViv((IV)month)));
774         PUSHs(sv_2mortal(newSViv((IV)day)));
775     }
776     else DATECALC_DATE_ERROR;
777 }
778 
779 
780 void
DateCalc_Add_N_Delta_YMDHMS(year,month,day,hour,min,sec,D_y,D_m,D_d,Dhh,Dmm,Dss)781 DateCalc_Add_N_Delta_YMDHMS(year,month,day, hour,min,sec, D_y,D_m,D_d, Dhh,Dmm,Dss)
782     Z_int	year
783     Z_int	month
784     Z_int	day
785     Z_int	hour
786     Z_int	min
787     Z_int	sec
788     Z_long	D_y
789     Z_long	D_m
790     Z_long	D_d
791     Z_long	Dhh
792     Z_long	Dmm
793     Z_long	Dss
794 PPCODE:
795 {
796     if (DateCalc_check_date(year,month,day))
797     {
798         if (DateCalc_check_time(hour,min,sec))
799         {
800             if (DateCalc_add_norm_delta_ymdhms(&year,&month,&day,
801                                                &hour,&min,&sec,
802                                                D_y,D_m,D_d,
803                                                Dhh,Dmm,Dss))
804             {
805                 EXTEND(sp,6);
806                 PUSHs(sv_2mortal(newSViv((IV)year)));
807                 PUSHs(sv_2mortal(newSViv((IV)month)));
808                 PUSHs(sv_2mortal(newSViv((IV)day)));
809                 PUSHs(sv_2mortal(newSViv((IV)hour)));
810                 PUSHs(sv_2mortal(newSViv((IV)min)));
811                 PUSHs(sv_2mortal(newSViv((IV)sec)));
812             }
813             else DATECALC_DATE_ERROR;
814         }
815         else DATECALC_TIME_ERROR;
816     }
817     else DATECALC_DATE_ERROR;
818 }
819 
820 
821 void
DateCalc_System_Clock(...)822 DateCalc_System_Clock(...)
823 PPCODE:
824 {
825     Z_int   year;
826     Z_int   month;
827     Z_int   day;
828     Z_int   hour;
829     Z_int   min;
830     Z_int   sec;
831     Z_int   doy;
832     Z_int   dow;
833     Z_int   dst;
834     boolean gmt;
835 
836     if ((items == 0) or (items == 1))
837     {
838         if (items == 1) gmt = (boolean) SvIV( ST(0) );
839         else            gmt = false;
840         if (DateCalc_system_clock(&year,&month,&day,
841                                   &hour,&min,&sec,
842                                   &doy,&dow,&dst,
843                                   gmt))
844         {
845             EXTEND(sp,9);
846             PUSHs(sv_2mortal(newSViv((IV)year)));
847             PUSHs(sv_2mortal(newSViv((IV)month)));
848             PUSHs(sv_2mortal(newSViv((IV)day)));
849             PUSHs(sv_2mortal(newSViv((IV)hour)));
850             PUSHs(sv_2mortal(newSViv((IV)min)));
851             PUSHs(sv_2mortal(newSViv((IV)sec)));
852             PUSHs(sv_2mortal(newSViv((IV)doy)));
853             PUSHs(sv_2mortal(newSViv((IV)dow)));
854             PUSHs(sv_2mortal(newSViv((IV)dst)));
855         }
856         else DATECALC_SYSTEM_ERROR;
857     }
858     else croak("Usage: Date::Calc::System_Clock([gmt])");
859 }
860 
861 
862 void
DateCalc_Today(...)863 DateCalc_Today(...)
864 PPCODE:
865 {
866     Z_int   year;
867     Z_int   month;
868     Z_int   day;
869     Z_int   hour;
870     Z_int   min;
871     Z_int   sec;
872     Z_int   doy;
873     Z_int   dow;
874     Z_int   dst;
875     boolean gmt;
876 
877     if ((items == 0) or (items == 1))
878     {
879         if (items == 1) gmt = (boolean) SvIV( ST(0) );
880         else            gmt = false;
881         if (DateCalc_system_clock(&year,&month,&day,
882                                   &hour,&min,&sec,
883                                   &doy,&dow,&dst,
884                                   gmt))
885         {
886             EXTEND(sp,3);
887             PUSHs(sv_2mortal(newSViv((IV)year)));
888             PUSHs(sv_2mortal(newSViv((IV)month)));
889             PUSHs(sv_2mortal(newSViv((IV)day)));
890         }
891         else DATECALC_SYSTEM_ERROR;
892     }
893     else croak("Usage: Date::Calc::Today([gmt])");
894 }
895 
896 
897 void
DateCalc_Now(...)898 DateCalc_Now(...)
899 PPCODE:
900 {
901     Z_int   year;
902     Z_int   month;
903     Z_int   day;
904     Z_int   hour;
905     Z_int   min;
906     Z_int   sec;
907     Z_int   doy;
908     Z_int   dow;
909     Z_int   dst;
910     boolean gmt;
911 
912     if ((items == 0) or (items == 1))
913     {
914         if (items == 1) gmt = (boolean) SvIV( ST(0) );
915         else            gmt = false;
916         if (DateCalc_system_clock(&year,&month,&day,
917                                   &hour,&min,&sec,
918                                   &doy,&dow,&dst,
919                                   gmt))
920         {
921             EXTEND(sp,3);
922             PUSHs(sv_2mortal(newSViv((IV)hour)));
923             PUSHs(sv_2mortal(newSViv((IV)min)));
924             PUSHs(sv_2mortal(newSViv((IV)sec)));
925         }
926         else DATECALC_SYSTEM_ERROR;
927     }
928     else croak("Usage: Date::Calc::Now([gmt])");
929 }
930 
931 
932 void
DateCalc_Today_and_Now(...)933 DateCalc_Today_and_Now(...)
934 PPCODE:
935 {
936     Z_int   year;
937     Z_int   month;
938     Z_int   day;
939     Z_int   hour;
940     Z_int   min;
941     Z_int   sec;
942     Z_int   doy;
943     Z_int   dow;
944     Z_int   dst;
945     boolean gmt;
946 
947     if ((items == 0) or (items == 1))
948     {
949         if (items == 1) gmt = (boolean) SvIV( ST(0) );
950         else            gmt = false;
951         if (DateCalc_system_clock(&year,&month,&day,
952                                   &hour,&min,&sec,
953                                   &doy,&dow,&dst,
954                                   gmt))
955         {
956             EXTEND(sp,6);
957             PUSHs(sv_2mortal(newSViv((IV)year)));
958             PUSHs(sv_2mortal(newSViv((IV)month)));
959             PUSHs(sv_2mortal(newSViv((IV)day)));
960             PUSHs(sv_2mortal(newSViv((IV)hour)));
961             PUSHs(sv_2mortal(newSViv((IV)min)));
962             PUSHs(sv_2mortal(newSViv((IV)sec)));
963         }
964         else DATECALC_SYSTEM_ERROR;
965     }
966     else croak("Usage: Date::Calc::Today_and_Now([gmt])");
967 }
968 
969 
970 void
DateCalc_This_Year(...)971 DateCalc_This_Year(...)
972 PPCODE:
973 {
974     Z_int   year;
975     Z_int   month;
976     Z_int   day;
977     Z_int   hour;
978     Z_int   min;
979     Z_int   sec;
980     Z_int   doy;
981     Z_int   dow;
982     Z_int   dst;
983     boolean gmt;
984 
985     if ((items == 0) or (items == 1))
986     {
987         if (items == 1) gmt = (boolean) SvIV( ST(0) );
988         else            gmt = false;
989         if (DateCalc_system_clock(&year,&month,&day,
990                                   &hour,&min,&sec,
991                                   &doy,&dow,&dst,
992                                   gmt))
993         {
994             EXTEND(sp,1);
995             PUSHs(sv_2mortal(newSViv((IV)year)));
996         }
997         else DATECALC_SYSTEM_ERROR;
998     }
999     else croak("Usage: Date::Calc::This_Year([gmt])");
1000 }
1001 
1002 
1003 void
DateCalc_Gmtime(...)1004 DateCalc_Gmtime(...)
1005 PPCODE:
1006 {
1007 #ifdef MACOS_TRADITIONAL
1008     double  f_seconds;
1009 #endif
1010     time_t  seconds;
1011     Z_int   year;
1012     Z_int   month;
1013     Z_int   day;
1014     Z_int   hour;
1015     Z_int   min;
1016     Z_int   sec;
1017     Z_int   doy;
1018     Z_int   dow;
1019     Z_int   dst;
1020 
1021     if ((items == 0) or (items == 1))
1022     {
1023 #ifdef MACOS_TRADITIONAL
1024         if (items == 1) f_seconds = (double) SvNV( ST(0) );
1025         else            f_seconds = (double) time(NULL);
1026         if ((f_seconds < 0) or (f_seconds > 0xFFFFFFFF))
1027             DATECALC_TIME_RANGE_ERROR;
1028         seconds = (time_t) f_seconds;
1029 #else
1030         if (items == 1) seconds = (time_t) SvIV( ST(0) );
1031         else            seconds = time(NULL);
1032 #endif
1033         if (DateCalc_gmtime(&year,&month,&day,
1034                             &hour,&min,&sec,
1035                             &doy,&dow,&dst,
1036                             seconds))
1037         {
1038             EXTEND(sp,9);
1039             PUSHs(sv_2mortal(newSViv((IV)year)));
1040             PUSHs(sv_2mortal(newSViv((IV)month)));
1041             PUSHs(sv_2mortal(newSViv((IV)day)));
1042             PUSHs(sv_2mortal(newSViv((IV)hour)));
1043             PUSHs(sv_2mortal(newSViv((IV)min)));
1044             PUSHs(sv_2mortal(newSViv((IV)sec)));
1045             PUSHs(sv_2mortal(newSViv((IV)doy)));
1046             PUSHs(sv_2mortal(newSViv((IV)dow)));
1047             PUSHs(sv_2mortal(newSViv((IV)dst)));
1048         }
1049         else DATECALC_TIME_RANGE_ERROR;
1050     }
1051     else croak("Usage: Date::Calc::Gmtime([time])");
1052 }
1053 
1054 
1055 void
DateCalc_Localtime(...)1056 DateCalc_Localtime(...)
1057 PPCODE:
1058 {
1059 #ifdef MACOS_TRADITIONAL
1060     double  f_seconds;
1061 #endif
1062     time_t  seconds;
1063     Z_int   year;
1064     Z_int   month;
1065     Z_int   day;
1066     Z_int   hour;
1067     Z_int   min;
1068     Z_int   sec;
1069     Z_int   doy;
1070     Z_int   dow;
1071     Z_int   dst;
1072 
1073     if ((items == 0) or (items == 1))
1074     {
1075 #ifdef MACOS_TRADITIONAL
1076         if (items == 1) f_seconds = (double) SvNV( ST(0) );
1077         else            f_seconds = (double) time(NULL);
1078         if ((f_seconds < 0) or (f_seconds > 0xFFFFFFFF))
1079             DATECALC_TIME_RANGE_ERROR;
1080         seconds = (time_t) f_seconds;
1081 #else
1082         if (items == 1) seconds = (time_t) SvIV( ST(0) );
1083         else            seconds = time(NULL);
1084 #endif
1085         if (DateCalc_localtime(&year,&month,&day,
1086                                &hour,&min,&sec,
1087                                &doy,&dow,&dst,
1088                                seconds))
1089         {
1090             EXTEND(sp,9);
1091             PUSHs(sv_2mortal(newSViv((IV)year)));
1092             PUSHs(sv_2mortal(newSViv((IV)month)));
1093             PUSHs(sv_2mortal(newSViv((IV)day)));
1094             PUSHs(sv_2mortal(newSViv((IV)hour)));
1095             PUSHs(sv_2mortal(newSViv((IV)min)));
1096             PUSHs(sv_2mortal(newSViv((IV)sec)));
1097             PUSHs(sv_2mortal(newSViv((IV)doy)));
1098             PUSHs(sv_2mortal(newSViv((IV)dow)));
1099             PUSHs(sv_2mortal(newSViv((IV)dst)));
1100         }
1101         else DATECALC_TIME_RANGE_ERROR;
1102     }
1103     else croak("Usage: Date::Calc::Localtime([time])");
1104 }
1105 
1106 
1107 void
DateCalc_Mktime(year,month,day,hour,min,sec)1108 DateCalc_Mktime(year,month,day, hour,min,sec)
1109     Z_int	year
1110     Z_int	month
1111     Z_int	day
1112     Z_int	hour
1113     Z_int	min
1114     Z_int	sec
1115 PPCODE:
1116 {
1117     time_t seconds;
1118 
1119     if (DateCalc_mktime(&seconds, year,month,day, hour,min,sec, -1,-1,-1))
1120     {
1121         EXTEND(sp,1);
1122 #ifdef MACOS_TRADITIONAL
1123         PUSHs(sv_2mortal(newSVuv((UV)seconds)));
1124 #else
1125         PUSHs(sv_2mortal(newSViv((IV)seconds)));
1126 #endif
1127     }
1128     else DATECALC_DATE_RANGE_ERROR;
1129 }
1130 
1131 
1132 void
DateCalc_Timezone(...)1133 DateCalc_Timezone(...)
1134 PPCODE:
1135 {
1136 #ifdef MACOS_TRADITIONAL
1137     double  f_when;
1138 #endif
1139     time_t  when;
1140     Z_int   year;
1141     Z_int   month;
1142     Z_int   day;
1143     Z_int   hour;
1144     Z_int   min;
1145     Z_int   sec;
1146     Z_int   dst;
1147 
1148     if ((items == 0) or (items == 1))
1149     {
1150 #ifdef MACOS_TRADITIONAL
1151         if (items == 1) f_when = (double) SvNV( ST(0) );
1152         else            f_when = (double) time(NULL);
1153         if ((f_when < 0) or (f_when > 0xFFFFFFFF))
1154             DATECALC_TIME_RANGE_ERROR;
1155         when = (time_t) f_when;
1156 #else
1157         if (items == 1) when = (time_t) SvIV( ST(0) );
1158         else            when = time(NULL);
1159 #endif
1160         if (DateCalc_timezone(&year,&month,&day,
1161                               &hour,&min,&sec,
1162                               &dst,when))
1163         {
1164             EXTEND(sp,7);
1165             PUSHs(sv_2mortal(newSViv((IV)year)));
1166             PUSHs(sv_2mortal(newSViv((IV)month)));
1167             PUSHs(sv_2mortal(newSViv((IV)day)));
1168             PUSHs(sv_2mortal(newSViv((IV)hour)));
1169             PUSHs(sv_2mortal(newSViv((IV)min)));
1170             PUSHs(sv_2mortal(newSViv((IV)sec)));
1171             PUSHs(sv_2mortal(newSViv((IV)dst)));
1172         }
1173         else DATECALC_TIME_RANGE_ERROR;
1174     }
1175     else croak("Usage: Date::Calc::Timezone([time])");
1176 }
1177 
1178 
1179 void
DateCalc_Date_to_Time(year,month,day,hour,min,sec)1180 DateCalc_Date_to_Time(year,month,day, hour,min,sec)
1181     Z_int	year
1182     Z_int	month
1183     Z_int	day
1184     Z_int	hour
1185     Z_int	min
1186     Z_int	sec
1187 PPCODE:
1188 {
1189     time_t seconds;
1190 
1191     if (DateCalc_date2time(&seconds, year,month,day, hour,min,sec))
1192     {
1193         EXTEND(sp,1);
1194 #ifdef MACOS_TRADITIONAL
1195         PUSHs(sv_2mortal(newSVuv((UV)seconds)));
1196 #else
1197         PUSHs(sv_2mortal(newSViv((IV)seconds)));
1198 #endif
1199     }
1200     else DATECALC_DATE_RANGE_ERROR;
1201 }
1202 
1203 
1204 void
DateCalc_Time_to_Date(...)1205 DateCalc_Time_to_Date(...)
1206 PPCODE:
1207 {
1208 #ifdef MACOS_TRADITIONAL
1209     double  f_seconds;
1210 #endif
1211     time_t  seconds;
1212     Z_int   year;
1213     Z_int   month;
1214     Z_int   day;
1215     Z_int   hour;
1216     Z_int   min;
1217     Z_int   sec;
1218 
1219     if ((items == 0) or (items == 1))
1220     {
1221 #ifdef MACOS_TRADITIONAL
1222         if (items == 1) f_seconds = (double) SvNV( ST(0) );
1223         else            f_seconds = (double) time(NULL);
1224         if ((f_seconds < 0) or (f_seconds > 0xFFFFFFFF))
1225             DATECALC_TIME_RANGE_ERROR;
1226         seconds = (time_t) f_seconds;
1227 #else
1228         if (items == 1) seconds = (time_t) SvIV( ST(0) );
1229         else            seconds = time(NULL);
1230 #endif
1231         if (DateCalc_time2date(&year,&month,&day, &hour,&min,&sec, seconds))
1232         {
1233             EXTEND(sp,6);
1234             PUSHs(sv_2mortal(newSViv((IV)year)));
1235             PUSHs(sv_2mortal(newSViv((IV)month)));
1236             PUSHs(sv_2mortal(newSViv((IV)day)));
1237             PUSHs(sv_2mortal(newSViv((IV)hour)));
1238             PUSHs(sv_2mortal(newSViv((IV)min)));
1239             PUSHs(sv_2mortal(newSViv((IV)sec)));
1240         }
1241         else DATECALC_TIME_RANGE_ERROR;
1242     }
1243     else croak("Usage: Date::Calc::Time_to_Date([time])");
1244 }
1245 
1246 
1247 void
DateCalc_Easter_Sunday(year)1248 DateCalc_Easter_Sunday(year)
1249     Z_int	year
1250 PPCODE:
1251 {
1252     Z_int month;
1253     Z_int day;
1254 
1255     if ((year > 0) and DateCalc_easter_sunday(&year,&month,&day))
1256     {
1257         EXTEND(sp,3);
1258         PUSHs(sv_2mortal(newSViv((IV)year)));
1259         PUSHs(sv_2mortal(newSViv((IV)month)));
1260         PUSHs(sv_2mortal(newSViv((IV)day)));
1261     }
1262     else DATECALC_YEAR_ERROR;
1263 }
1264 
1265 
1266 void
DateCalc_Decode_Month(...)1267 DateCalc_Decode_Month(...)
1268 PPCODE:
1269 {
1270     charptr string;
1271     N_int   length;
1272     Z_int   lang;
1273 
1274     if ((items == 1) or (items == 2))
1275     {
1276         if ( DATECALC_STRING(ST(0),string,length) )
1277         {
1278             if (items == 2)
1279             {
1280                 if ( not DATECALC_SCALAR(ST(1),Z_int,lang) )
1281                     DATECALC_SCALAR_ERROR;
1282             }
1283             else lang = 0;
1284             EXTEND(sp,1);
1285             PUSHs(sv_2mortal(newSViv((IV)DateCalc_Decode_Month(string,length,lang))));
1286         }
1287         else DATECALC_STRING_ERROR;
1288     }
1289     else croak("Usage: Date::Calc::Decode_Month(string[,lang])");
1290 }
1291 
1292 
1293 void
DateCalc_Decode_Day_of_Week(...)1294 DateCalc_Decode_Day_of_Week(...)
1295 PPCODE:
1296 {
1297     charptr string;
1298     N_int   length;
1299     Z_int   lang;
1300 
1301     if ((items == 1) or (items == 2))
1302     {
1303         if ( DATECALC_STRING(ST(0),string,length) )
1304         {
1305             if (items == 2)
1306             {
1307                 if ( not DATECALC_SCALAR(ST(1),Z_int,lang) )
1308                     DATECALC_SCALAR_ERROR;
1309             }
1310             else lang = 0;
1311             EXTEND(sp,1);
1312             PUSHs(sv_2mortal(newSViv((IV)DateCalc_Decode_Day_of_Week(string,length,lang))));
1313         }
1314         else DATECALC_STRING_ERROR;
1315     }
1316     else croak("Usage: Date::Calc::Decode_Day_of_Week(string[,lang])");
1317 }
1318 
1319 
1320 Z_int
DateCalc_Decode_Language(string)1321 DateCalc_Decode_Language(string)
1322     charptr	string
1323 CODE:
1324 {
1325     RETVAL = DateCalc_Decode_Language(string,strlen((char *)string));
1326 }
1327 OUTPUT:
1328 RETVAL
1329 
1330 
1331 void
DateCalc_Decode_Date_EU(...)1332 DateCalc_Decode_Date_EU(...)
1333 PPCODE:
1334 {
1335     charptr string;
1336     N_int   length;
1337     Z_int   lang;
1338     Z_int   year;
1339     Z_int   month;
1340     Z_int   day;
1341 
1342     if ((items == 1) or (items == 2))
1343     {
1344         if ( DATECALC_STRING(ST(0),string,length) )
1345         {
1346             if (items == 2)
1347             {
1348                 if ( not DATECALC_SCALAR(ST(1),Z_int,lang) )
1349                     DATECALC_SCALAR_ERROR;
1350             }
1351             else lang = 0;
1352             if (DateCalc_decode_date_eu(string,&year,&month,&day,lang))
1353             {
1354                 EXTEND(sp,3);
1355                 PUSHs(sv_2mortal(newSViv((IV)year)));
1356                 PUSHs(sv_2mortal(newSViv((IV)month)));
1357                 PUSHs(sv_2mortal(newSViv((IV)day)));
1358             }
1359             /* else return empty list */
1360         }
1361         else DATECALC_STRING_ERROR;
1362     }
1363     else croak("Usage: Date::Calc::Decode_Date_EU(string[,lang])");
1364 }
1365 
1366 
1367 void
DateCalc_Decode_Date_US(...)1368 DateCalc_Decode_Date_US(...)
1369 PPCODE:
1370 {
1371     charptr string;
1372     N_int   length;
1373     Z_int   lang;
1374     Z_int   year;
1375     Z_int   month;
1376     Z_int   day;
1377 
1378     if ((items == 1) or (items == 2))
1379     {
1380         if ( DATECALC_STRING(ST(0),string,length) )
1381         {
1382             if (items == 2)
1383             {
1384                 if ( not DATECALC_SCALAR(ST(1),Z_int,lang) )
1385                     DATECALC_SCALAR_ERROR;
1386             }
1387             else lang = 0;
1388             if (DateCalc_decode_date_us(string,&year,&month,&day,lang))
1389             {
1390                 EXTEND(sp,3);
1391                 PUSHs(sv_2mortal(newSViv((IV)year)));
1392                 PUSHs(sv_2mortal(newSViv((IV)month)));
1393                 PUSHs(sv_2mortal(newSViv((IV)day)));
1394             }
1395             /* else return empty list */
1396         }
1397         else DATECALC_STRING_ERROR;
1398     }
1399     else croak("Usage: Date::Calc::Decode_Date_US(string[,lang])");
1400 }
1401 
1402 
1403 Z_int
DateCalc_Fixed_Window(year)1404 DateCalc_Fixed_Window(year)
1405     Z_int	year
1406 
1407 
1408 Z_int
1409 DateCalc_Moving_Window(year)
1410     Z_int	year
1411 
1412 
1413 Z_int
1414 DateCalc_Compress(year,month,day)
1415     Z_int	year
1416     Z_int	month
1417     Z_int	day
1418 
1419 
1420 void
1421 DateCalc_Uncompress(date)
1422     Z_int	date
1423 PPCODE:
1424 {
1425     Z_int century;
1426     Z_int year;
1427     Z_int month;
1428     Z_int day;
1429 
1430     if (DateCalc_uncompress(date,&century,&year,&month,&day))
1431     {
1432         EXTEND(sp,4);
1433         PUSHs(sv_2mortal(newSViv((IV)century)));
1434         PUSHs(sv_2mortal(newSViv((IV)year)));
1435         PUSHs(sv_2mortal(newSViv((IV)month)));
1436         PUSHs(sv_2mortal(newSViv((IV)day)));
1437     }
1438     /* else return empty list */
1439     /* else DATECALC_DATE_ERROR; */
1440 }
1441 
1442 
1443 boolean
DateCalc_check_compressed(date)1444 DateCalc_check_compressed(date)
1445     Z_int	date
1446 
1447 
1448 void
1449 DateCalc_Compressed_to_Text(...)
1450 PPCODE:
1451 {
1452     charptr string;
1453     Z_int   date;
1454     Z_int   lang;
1455 
1456     if ((items == 1) or (items == 2))
1457     {
1458         if ( DATECALC_SCALAR(ST(0),Z_int,date) )
1459         {
1460             if (items == 2)
1461             {
1462                 if ( not DATECALC_SCALAR(ST(1),Z_int,lang) )
1463                     DATECALC_SCALAR_ERROR;
1464             }
1465             else lang = 0;
1466             string = DateCalc_Compressed_to_Text(date,lang);
1467             if (string != NULL)
1468             {
1469                 EXTEND(sp,1);
1470                 PUSHs(sv_2mortal(newSVpv((char *)string,0)));
1471                 DateCalc_Dispose(string);
1472             }
1473             else DATECALC_MEMORY_ERROR;
1474         }
1475         else DATECALC_SCALAR_ERROR;
1476     }
1477     else croak("Usage: Date::Calc::Compressed_to_Text(date[,lang])");
1478 }
1479 
1480 
1481 void
DateCalc_Date_to_Text(...)1482 DateCalc_Date_to_Text(...)
1483 PPCODE:
1484 {
1485     charptr string;
1486     Z_int   year;
1487     Z_int   month;
1488     Z_int   day;
1489     Z_int   lang;
1490 
1491     if ((items == 3) or (items == 4))
1492     {
1493         if ( DATECALC_SCALAR(ST(0),Z_int,year)  and
1494              DATECALC_SCALAR(ST(1),Z_int,month) and
1495              DATECALC_SCALAR(ST(2),Z_int,day) )
1496         {
1497             if (items == 4)
1498             {
1499                 if ( not DATECALC_SCALAR(ST(3),Z_int,lang) )
1500                     DATECALC_SCALAR_ERROR;
1501             }
1502             else lang = 0;
1503             if (DateCalc_check_date(year,month,day))
1504             {
1505                 string = DateCalc_Date_to_Text(year,month,day,lang);
1506                 if (string != NULL)
1507                 {
1508                     EXTEND(sp,1);
1509                     PUSHs(sv_2mortal(newSVpv((char *)string,0)));
1510                     DateCalc_Dispose(string);
1511                 }
1512                 else DATECALC_MEMORY_ERROR;
1513             }
1514             else DATECALC_DATE_ERROR;
1515         }
1516         else DATECALC_SCALAR_ERROR;
1517     }
1518     else croak("Usage: Date::Calc::Date_to_Text(year,month,day[,lang])");
1519 }
1520 
1521 
1522 void
DateCalc_Date_to_Text_Long(...)1523 DateCalc_Date_to_Text_Long(...)
1524 PPCODE:
1525 {
1526     charptr string;
1527     Z_int   year;
1528     Z_int   month;
1529     Z_int   day;
1530     Z_int   lang;
1531 
1532     if ((items == 3) or (items == 4))
1533     {
1534         if ( DATECALC_SCALAR(ST(0),Z_int,year)  and
1535              DATECALC_SCALAR(ST(1),Z_int,month) and
1536              DATECALC_SCALAR(ST(2),Z_int,day) )
1537         {
1538             if (items == 4)
1539             {
1540                 if ( not DATECALC_SCALAR(ST(3),Z_int,lang) )
1541                     DATECALC_SCALAR_ERROR;
1542             }
1543             else lang = 0;
1544             if (DateCalc_check_date(year,month,day))
1545             {
1546                 string = DateCalc_Date_to_Text_Long(year,month,day,lang);
1547                 if (string != NULL)
1548                 {
1549                     EXTEND(sp,1);
1550                     PUSHs(sv_2mortal(newSVpv((char *)string,0)));
1551                     DateCalc_Dispose(string);
1552                 }
1553                 else DATECALC_MEMORY_ERROR;
1554             }
1555             else DATECALC_DATE_ERROR;
1556         }
1557         else DATECALC_SCALAR_ERROR;
1558     }
1559     else croak("Usage: Date::Calc::Date_to_Text_Long(year,month,day[,lang])");
1560 }
1561 
1562 
1563 void
DateCalc_English_Ordinal(number)1564 DateCalc_English_Ordinal(number)
1565     Z_int	number
1566 PPCODE:
1567 {
1568     blockdef(string,64);
1569 
1570     DateCalc_English_Ordinal(string,number);
1571     EXTEND(sp,1);
1572     PUSHs(sv_2mortal(newSVpv((char *)string,0)));
1573 }
1574 
1575 
1576 void
DateCalc_Calendar(...)1577 DateCalc_Calendar(...)
1578 PPCODE:
1579 {
1580     charptr string;
1581     Z_int   year;
1582     Z_int   month;
1583     boolean orthodox;
1584     Z_int   lang;
1585 
1586     if ((items >= 2) and (items <= 4))
1587     {
1588         if ( DATECALC_SCALAR(ST(0),Z_int,year)  and
1589              DATECALC_SCALAR(ST(1),Z_int,month) )
1590         {
1591             if (items > 2)
1592             {
1593                 if ( not DATECALC_SCALAR(ST(2),boolean,orthodox) )
1594                     DATECALC_SCALAR_ERROR;
1595                 if (items > 3)
1596                 {
1597                     if ( not DATECALC_SCALAR(ST(3),Z_int,lang) )
1598                         DATECALC_SCALAR_ERROR;
1599                 }
1600                 else { lang = 0; }
1601             }
1602             else { orthodox = false; lang = 0; }
1603             if (year > 0)
1604             {
1605                 if ((month >= 1) and (month <= 12))
1606                 {
1607                     string = DateCalc_Calendar(year,month,orthodox,lang);
1608                     if (string != NULL)
1609                     {
1610                         EXTEND(sp,1);
1611                         PUSHs(sv_2mortal(newSVpv((char *)string,0)));
1612                         DateCalc_Dispose(string);
1613                     }
1614                     else DATECALC_MEMORY_ERROR;
1615                 }
1616                 else DATECALC_MONTH_ERROR;
1617             }
1618             else DATECALC_YEAR_ERROR;
1619         }
1620         else DATECALC_SCALAR_ERROR;
1621     }
1622     else croak("Usage: Date::Calc::Calendar(year,month[,orthodox[,lang]])");
1623 }
1624 
1625 
1626 void
DateCalc_Month_to_Text(...)1627 DateCalc_Month_to_Text(...)
1628 PPCODE:
1629 {
1630     Z_int   month;
1631     Z_int   lang = 0;
1632 
1633     if ((items == 1) or (items == 2))
1634     {
1635         if ( DATECALC_SCALAR(ST(0),Z_int,month) )
1636         {
1637             if (items == 2)
1638             {
1639                 if ( not DATECALC_SCALAR(ST(1),Z_int,lang) )
1640                     DATECALC_SCALAR_ERROR;
1641             }
1642             if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
1643             if ((month >= 1) and (month <= 12))
1644             {
1645                 EXTEND(sp,1);
1646                 PUSHs(sv_2mortal(newSVpv((char *)DateCalc_Month_to_Text_[lang][month],0)));
1647             }
1648             else DATECALC_MONTH_ERROR;
1649         }
1650         else DATECALC_SCALAR_ERROR;
1651     }
1652     else croak("Usage: Date::Calc::Month_to_Text(month[,lang])");
1653 }
1654 
1655 
1656 void
DateCalc_Day_of_Week_to_Text(...)1657 DateCalc_Day_of_Week_to_Text(...)
1658 PPCODE:
1659 {
1660     Z_int   dow;
1661     Z_int   lang = 0;
1662 
1663     if ((items == 1) or (items == 2))
1664     {
1665         if ( DATECALC_SCALAR(ST(0),Z_int,dow) )
1666         {
1667             if (items == 2)
1668             {
1669                 if ( not DATECALC_SCALAR(ST(1),Z_int,lang) )
1670                     DATECALC_SCALAR_ERROR;
1671             }
1672             if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
1673             if ((dow >= 1) and (dow <= 7))
1674             {
1675                 EXTEND(sp,1);
1676                 PUSHs(sv_2mortal(newSVpv((char *)DateCalc_Day_of_Week_to_Text_[lang][dow],0)));
1677             }
1678             else DATECALC_DAYOFWEEK_ERROR;
1679         }
1680         else DATECALC_SCALAR_ERROR;
1681     }
1682     else croak("Usage: Date::Calc::Day_of_Week_to_Text(dow[,lang])");
1683 }
1684 
1685 
1686 void
DateCalc_Day_of_Week_Abbreviation(...)1687 DateCalc_Day_of_Week_Abbreviation(...)
1688 PPCODE:
1689 {
1690     blockdef(buffer,4);
1691     Z_int   dow;
1692     Z_int   lang = 0;
1693 
1694     if ((items == 1) or (items == 2))
1695     {
1696         if ( DATECALC_SCALAR(ST(0),Z_int,dow) )
1697         {
1698             if (items == 2)
1699             {
1700                 if ( not DATECALC_SCALAR(ST(1),Z_int,lang) )
1701                     DATECALC_SCALAR_ERROR;
1702             }
1703             if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
1704             if ((dow >= 1) and (dow <= 7))
1705             {
1706                 EXTEND(sp,1);
1707                 if (DateCalc_Day_of_Week_Abbreviation_[lang][0][0] != '\0')
1708                 {
1709                     PUSHs(sv_2mortal(newSVpv((char *)DateCalc_Day_of_Week_Abbreviation_[lang][dow],0)));
1710                 }
1711                 else
1712                 {
1713                     strncpy((char *)buffer,(char *)DateCalc_Day_of_Week_to_Text_[lang][dow],3);
1714                     buffer[3] = '\0';
1715                     PUSHs(sv_2mortal(newSVpv((char *)buffer,0)));
1716                 }
1717             }
1718             else DATECALC_DAYOFWEEK_ERROR;
1719         }
1720         else DATECALC_SCALAR_ERROR;
1721     }
1722     else croak("Usage: Date::Calc::Day_of_Week_Abbreviation(dow[,lang])");
1723 }
1724 
1725 
1726 void
DateCalc_Language_to_Text(lang)1727 DateCalc_Language_to_Text(lang)
1728     Z_int	lang
1729 PPCODE:
1730 {
1731     if ((lang >= 1) and (lang <= DateCalc_LANGUAGES))
1732     {
1733         EXTEND(sp,1);
1734         PUSHs(sv_2mortal(newSVpv((char *)DateCalc_Language_to_Text_[lang],0)));
1735     }
1736     else DATECALC_LANGUAGE_ERROR;
1737 }
1738 
1739 
1740 Z_int
DateCalc_Language(...)1741 DateCalc_Language(...)
1742 CODE:
1743 {
1744     Z_int lang;
1745 
1746     if ((items >= 0) and (items <= 1))
1747     {
1748         RETVAL = DateCalc_Language;
1749         if (items == 1)
1750         {
1751             if ( not DATECALC_SCALAR(ST(0),Z_int,lang) )
1752                 DATECALC_SCALAR_ERROR;
1753             if ((lang >= 1) and (lang <= DateCalc_LANGUAGES))
1754             {
1755                 DateCalc_Language = lang;
1756             }
1757             else DATECALC_LANGUAGE_ERROR;
1758         }
1759     }
1760     else croak("Usage: Date::Calc::Language([lang])");
1761 }
1762 OUTPUT:
1763 RETVAL
1764 
1765 
1766 Z_int
DateCalc_Languages()1767 DateCalc_Languages()
1768 CODE:
1769 {
1770     RETVAL = DateCalc_LANGUAGES;
1771 }
1772 OUTPUT:
1773 RETVAL
1774 
1775 
1776 void
DateCalc_ISO_LC(scalar)1777 DateCalc_ISO_LC(scalar)
1778     SV *	scalar
1779 PPCODE:
1780 {
1781     charptr string;
1782     charptr buffer;
1783     N_int length;
1784     N_int index;
1785 
1786     if ( DATECALC_STRING(scalar,string,length) )
1787     {
1788         buffer = (charptr) malloc(length+1);
1789         if (buffer != NULL)
1790         {
1791             for ( index = 0; index < length; index++ )
1792                 buffer[index] = DateCalc_ISO_LC(string[index]);
1793             buffer[length] = '\0';
1794             EXTEND(sp,1);
1795             PUSHs(sv_2mortal(newSVpv((char *)buffer,length)));
1796             free(buffer);
1797         }
1798         else DATECALC_MEMORY_ERROR;
1799     }
1800     else DATECALC_STRING_ERROR;
1801 }
1802 
1803 
1804 void
DateCalc_ISO_UC(scalar)1805 DateCalc_ISO_UC(scalar)
1806     SV *	scalar
1807 PPCODE:
1808 {
1809     charptr string;
1810     charptr buffer;
1811     N_int length;
1812     N_int index;
1813 
1814     if ( DATECALC_STRING(scalar,string,length) )
1815     {
1816         buffer = (charptr) malloc(length+1);
1817         if (buffer != NULL)
1818         {
1819             for ( index = 0; index < length; index++ )
1820                 buffer[index] = DateCalc_ISO_UC(string[index]);
1821             buffer[length] = '\0';
1822             EXTEND(sp,1);
1823             PUSHs(sv_2mortal(newSVpv((char *)buffer,length)));
1824             free(buffer);
1825         }
1826         else DATECALC_MEMORY_ERROR;
1827     }
1828     else DATECALC_STRING_ERROR;
1829 }
1830 
1831 
1832 void
DateCalc_Version()1833 DateCalc_Version()
1834 PPCODE:
1835 {
1836     charptr string;
1837 
1838     string = DateCalc_Version();
1839     if (string != NULL)
1840     {
1841         EXTEND(sp,1);
1842         PUSHs(sv_2mortal(newSVpv((char *)string,0)));
1843     }
1844     else DATECALC_MEMORY_ERROR;
1845 }
1846 
1847 
1848