mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* time.c: remove time_t restriction from Time class.
* timev.h: new file to define struct vtm. * strftime.c: format struct vtm instead of struct tm. * ext/syck/rubyext.c (mktime_do): don't use time_t; [ruby-dev:38191] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@23242 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									143846ad36
								
							
						
					
					
						commit
						3bc16f62c1
					
				
					 7 changed files with 1612 additions and 543 deletions
				
			
		
							
								
								
									
										12
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								ChangeLog
									
										
									
									
									
								
							|  | @ -1,3 +1,15 @@ | |||
| Tue Apr 21 23:52:45 2009  Tanaka Akira  <akr@fsij.org> | ||||
| 
 | ||||
| 	* time.c: remove time_t restriction from Time class. | ||||
| 
 | ||||
| 	* timev.h: new file to define struct vtm. | ||||
| 
 | ||||
| 	* strftime.c: format struct vtm instead of struct tm. | ||||
| 
 | ||||
| 	* ext/syck/rubyext.c (mktime_do): don't use time_t; | ||||
| 
 | ||||
| 	[ruby-dev:38191] | ||||
| 
 | ||||
| Tue Apr 21 09:25:41 2009  Nobuyoshi Nakada  <nobu@ruby-lang.org> | ||||
| 
 | ||||
| 	* dir.c (dir_path, dir_each, glob_helper): use readdir_r() if | ||||
|  |  | |||
|  | @ -291,7 +291,7 @@ mktime_do(struct mktime_arg *arg) | |||
|     if ( len > ptr - str && ( *ptr == '-' || *ptr == '+' ) ) | ||||
|     { | ||||
|         time_t tz_offset = strtol(ptr, NULL, 10) * 3600; | ||||
|         time_t tmp; | ||||
|         VALUE tmp; | ||||
| 
 | ||||
|         while ( *ptr != ':' && *ptr != '\0' ) ptr++; | ||||
|         if ( *ptr == ':' ) | ||||
|  | @ -309,8 +309,9 @@ mktime_do(struct mktime_arg *arg) | |||
| 
 | ||||
|         /* Make TZ time*/ | ||||
|         time = rb_funcall(rb_cTime, s_utc, 6, year, mon, day, hour, min, sec); | ||||
|         tmp = NUM2LONG(rb_funcall(time, s_to_i, 0)) - tz_offset; | ||||
|         return rb_funcall(rb_cTime, s_at, 2, LONG2NUM(tmp), LONG2NUM(usec)); | ||||
|         tmp = rb_funcall(time, s_to_i, 0); | ||||
|         tmp = rb_funcall(tmp, '-', 1, LONG2FIX(tz_offset)); | ||||
|         return rb_funcall(rb_cTime, s_at, 2, tmp, LONG2NUM(usec)); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  |  | |||
							
								
								
									
										244
									
								
								strftime.c
									
										
									
									
									
								
							
							
						
						
									
										244
									
								
								strftime.c
									
										
									
									
									
								
							|  | @ -48,6 +48,7 @@ | |||
|  */ | ||||
| 
 | ||||
| #include "ruby/ruby.h" | ||||
| #include "timev.h" | ||||
| 
 | ||||
| #ifndef GAWK | ||||
| #include <stdio.h> | ||||
|  | @ -103,9 +104,13 @@ | |||
| #define const	/**/ | ||||
| static int weeknumber(); | ||||
| adddecl(static int iso8601wknum();) | ||||
| static int weeknumber_v(); | ||||
| adddecl(static int iso8601wknum_v();) | ||||
| #else | ||||
| static int weeknumber(const struct tm *timeptr, int firstweekday); | ||||
| adddecl(static int iso8601wknum(const struct tm *timeptr);) | ||||
| static int weeknumber_v(const struct vtm *vtm, int firstweekday); | ||||
| adddecl(static int iso8601wknum_v(const struct vtm *vtm);) | ||||
| #endif | ||||
| 
 | ||||
| #ifdef STDC_HEADERS | ||||
|  | @ -175,10 +180,17 @@ max(int a, int b) | |||
| #error No string literal concatenation | ||||
| #endif | ||||
| 
 | ||||
| #define add(x,y) (rb_funcall((x), '+', 1, (y))) | ||||
| #define sub(x,y) (rb_funcall((x), '-', 1, (y))) | ||||
| #define mul(x,y) (rb_funcall((x), '*', 1, (y))) | ||||
| #define quo(x,y) (rb_funcall((x), rb_intern("quo"), 1, (y))) | ||||
| #define div(x,y) (rb_funcall((x), rb_intern("div"), 1, (y))) | ||||
| #define mod(x,y) (rb_funcall((x), '%', 1, (y))) | ||||
| 
 | ||||
| /* strftime --- produce formatted time */ | ||||
| 
 | ||||
| size_t | ||||
| rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr, const struct timespec *ts, int gmt) | ||||
| rb_strftime(char *s, size_t maxsize, const char *format, const struct vtm *vtm, VALUE timev, int gmt) | ||||
| { | ||||
| 	char *endp = s + maxsize; | ||||
| 	char *start = s; | ||||
|  | @ -219,7 +231,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 	}; | ||||
| 	static const char ampm[][3] = { "AM", "PM", }; | ||||
| 
 | ||||
| 	if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0) | ||||
| 	if (s == NULL || format == NULL || vtm == NULL || maxsize == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* quick check if we even need to bother */ | ||||
|  | @ -293,7 +305,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 		} while (0) | ||||
| #define STRFTIME(fmt) \ | ||||
| 		do { \ | ||||
| 			i = rb_strftime(s, endp - s, fmt, timeptr, ts, gmt); \ | ||||
| 			i = rb_strftime(s, endp - s, fmt, vtm, timev, gmt); \ | ||||
| 			if (!i) return 0; \ | ||||
| 			if (precision > i) {\ | ||||
| 				memmove(s + precision - i, s, i);\ | ||||
|  | @ -302,6 +314,29 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 	                }\ | ||||
| 			else s += i; \ | ||||
| 		} while (0) | ||||
| #define FMTV(def_pad, def_prec, fmt, val) \ | ||||
|                 do { \ | ||||
|                         VALUE tmp = (val); \ | ||||
|                         if (FIXNUM_P(tmp)) { \ | ||||
|                                 FMT((def_pad), (def_prec), "l"fmt, FIX2LONG(tmp)); \ | ||||
|                         } \ | ||||
|                         else { \ | ||||
|                                 VALUE args[2], result; \ | ||||
|                                 size_t l; \ | ||||
|                                 if (precision <= 0) precision = (def_prec); \ | ||||
|                                 if (flags & BIT_OF(LEFT)) precision = 1; \ | ||||
|                                 args[0] = INT2FIX(precision); \ | ||||
|                                 args[1] = val; \ | ||||
|                                 if (padding == '0' || (!padding && def_pad == '0')) \ | ||||
|                                         result = rb_str_format(2, args, rb_str_new2("%0*"fmt)); \ | ||||
|                                 else \ | ||||
|                                         result = rb_str_format(2, args, rb_str_new2("%*"fmt)); \ | ||||
|                                 l = strlcpy(s, StringValueCStr(result), endp-s); \ | ||||
|                                 if ((size_t)(endp-s) <= l) \ | ||||
|                                         goto err; \ | ||||
|                                 s += l; \ | ||||
|                         } \ | ||||
|                 } while (0) | ||||
| 
 | ||||
| 		if (*format != '%') { | ||||
| 			*s++ = *format; | ||||
|  | @ -328,10 +363,10 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 				flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); | ||||
| 				flags |= BIT_OF(UPPER); | ||||
| 			} | ||||
| 			if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6) | ||||
| 			if (vtm->wday < 0 || vtm->wday > 6) | ||||
| 				i = 1, tp = "?"; | ||||
| 			else | ||||
| 				i = 3, tp = days_l[timeptr->tm_wday]; | ||||
| 				i = 3, tp = days_l[vtm->wday]; | ||||
| 			break; | ||||
| 
 | ||||
| 		case 'A':	/* full weekday name */ | ||||
|  | @ -339,10 +374,10 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 				flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); | ||||
| 				flags |= BIT_OF(UPPER); | ||||
| 			} | ||||
| 			if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6) | ||||
| 			if (vtm->wday < 0 || vtm->wday > 6) | ||||
| 				i = 1, tp = "?"; | ||||
| 			else | ||||
| 				i = strlen(tp = days_l[timeptr->tm_wday]); | ||||
| 				i = strlen(tp = days_l[vtm->wday]); | ||||
| 			break; | ||||
| 
 | ||||
| #ifdef SYSV_EXT | ||||
|  | @ -353,10 +388,10 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 				flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); | ||||
| 				flags |= BIT_OF(UPPER); | ||||
| 			} | ||||
| 			if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11) | ||||
| 			if (vtm->mon < 1 || vtm->mon > 12) | ||||
| 				i = 1, tp = "?"; | ||||
| 			else | ||||
| 				i = 3, tp = months_l[timeptr->tm_mon]; | ||||
| 				i = 3, tp = months_l[vtm->mon-1]; | ||||
| 			break; | ||||
| 
 | ||||
| 		case 'B':	/* full month name */ | ||||
|  | @ -364,10 +399,10 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 				flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); | ||||
| 				flags |= BIT_OF(UPPER); | ||||
| 			} | ||||
| 			if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11) | ||||
| 			if (vtm->mon < 1 || vtm->mon > 12) | ||||
| 				i = 1, tp = "?"; | ||||
| 			else | ||||
| 				i = strlen(tp = months_l[timeptr->tm_mon]); | ||||
| 				i = strlen(tp = months_l[vtm->mon-1]); | ||||
| 			break; | ||||
| 
 | ||||
| 		case 'c':	/* appropriate date and time representation */ | ||||
|  | @ -375,17 +410,17 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 			continue; | ||||
| 
 | ||||
| 		case 'd':	/* day of the month, 01 - 31 */ | ||||
| 			i = range(1, timeptr->tm_mday, 31); | ||||
| 			i = range(1, vtm->mday, 31); | ||||
| 			FMT('0', 2, "d", i); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'H':	/* hour, 24-hour clock, 00 - 23 */ | ||||
| 			i = range(0, timeptr->tm_hour, 23); | ||||
| 			i = range(0, vtm->hour, 23); | ||||
| 			FMT('0', 2, "d", i); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'I':	/* hour, 12-hour clock, 01 - 12 */ | ||||
| 			i = range(0, timeptr->tm_hour, 23); | ||||
| 			i = range(0, vtm->hour, 23); | ||||
| 			if (i == 0) | ||||
| 				i = 12; | ||||
| 			else if (i > 12) | ||||
|  | @ -394,16 +429,16 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 			continue; | ||||
| 
 | ||||
| 		case 'j':	/* day of the year, 001 - 366 */ | ||||
| 			FMT('0', 3, "d", timeptr->tm_yday + 1); | ||||
| 			FMT('0', 3, "d", vtm->yday); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'm':	/* month, 01 - 12 */ | ||||
| 			i = range(0, timeptr->tm_mon, 11); | ||||
| 			FMT('0', 2, "d", i + 1); | ||||
| 			i = range(1, vtm->mon, 12); | ||||
| 			FMT('0', 2, "d", i); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'M':	/* minute, 00 - 59 */ | ||||
| 			i = range(0, timeptr->tm_min, 59); | ||||
| 			i = range(0, vtm->min, 59); | ||||
| 			FMT('0', 2, "d", i); | ||||
| 			continue; | ||||
| 
 | ||||
|  | @ -414,7 +449,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 				flags &= ~(BIT_OF(UPPER)|BIT_OF(CHCASE)); | ||||
| 				flags |= BIT_OF(LOWER); | ||||
| 			} | ||||
| 			i = range(0, timeptr->tm_hour, 23); | ||||
| 			i = range(0, vtm->hour, 23); | ||||
| 			if (i < 12) | ||||
| 				tp = ampm[0]; | ||||
| 			else | ||||
|  | @ -423,25 +458,28 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 			break; | ||||
| 
 | ||||
| 		case 's': | ||||
| 			FMT('0', 1, "d", (int) ts->tv_sec); | ||||
| 			continue; | ||||
|                         { | ||||
|                                 VALUE sec = div(timev, INT2FIX(1)); | ||||
|                                 FMTV('0', 1, "d", sec); | ||||
|                                 continue; | ||||
|                         } | ||||
| 
 | ||||
| 		case 'S':	/* second, 00 - 60 */ | ||||
| 			i = range(0, timeptr->tm_sec, 60); | ||||
| 			i = range(0, vtm->sec, 60); | ||||
| 			FMT('0', 2, "d", i); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'U':	/* week of year, Sunday is first day of week */ | ||||
| 			FMT('0', 2, "d", weeknumber(timeptr, 0)); | ||||
| 			FMT('0', 2, "d", weeknumber_v(vtm, 0)); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'w':	/* weekday, Sunday == 0, 0 - 6 */ | ||||
| 			i = range(0, timeptr->tm_wday, 6); | ||||
| 			i = range(0, vtm->wday, 6); | ||||
| 			FMT('0', 1, "d", i); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'W':	/* week of year, Monday is first day of week */ | ||||
| 			FMT('0', 2, "d", weeknumber(timeptr, 1)); | ||||
| 			FMT('0', 2, "d", weeknumber_v(vtm, 1)); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'x':	/* appropriate date representation */ | ||||
|  | @ -453,12 +491,12 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 			continue; | ||||
| 
 | ||||
| 		case 'y':	/* year without a century, 00 - 99 */ | ||||
| 			i = timeptr->tm_year % 100; | ||||
| 			i = NUM2INT(mod(vtm->year, INT2FIX(100))); | ||||
| 			FMT('0', 2, "d", i); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'Y':	/* year with century */ | ||||
| 			FMT('0', 1, "ld", 1900L + timeptr->tm_year); | ||||
|                         FMTV('0', 1, "d", vtm->year); | ||||
| 			continue; | ||||
| 
 | ||||
| #ifdef MAILHEADER_EXT | ||||
|  | @ -484,6 +522,8 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 				off = 0; | ||||
| 			} | ||||
| 			else { | ||||
| 				off = NUM2LONG(rb_funcall(quo(vtm->utc_offset, INT2FIX(60)), rb_intern("round"), 0)); | ||||
| #if 0 | ||||
| #ifdef HAVE_TM_NAME | ||||
| 				/*
 | ||||
| 				 * Systems with tm_name probably have tm_tzadj as | ||||
|  | @ -521,6 +561,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| #endif /* !HAVE_VAR_TIMEZONE */ | ||||
| #endif /* !HAVE_TM_ZONE */ | ||||
| #endif /* !HAVE_TM_NAME */ | ||||
| #endif /* 0 */ | ||||
| 			} | ||||
| 			if (off < 0) { | ||||
| 				off = -off; | ||||
|  | @ -546,6 +587,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 				tp = "UTC"; | ||||
| 				break; | ||||
| 			} | ||||
| #if 0 | ||||
| #ifdef HAVE_TZNAME | ||||
| 			i = (daylight && timeptr->tm_isdst > 0); /* 0 or 1 */ | ||||
| 			tp = tzname[i]; | ||||
|  | @ -567,6 +609,8 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| #endif /* HAVE_TM_NAME */ | ||||
| #endif /* HAVE_TM_ZONE */ | ||||
| #endif /* HAVE_TZNAME */ | ||||
| #endif /* 0 */ | ||||
| 			tp = vtm->zone; | ||||
| 			i = strlen(tp); | ||||
| 			break; | ||||
| 
 | ||||
|  | @ -586,7 +630,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 			continue; | ||||
| 
 | ||||
| 		case 'e':	/* day of month, blank padded */ | ||||
| 			FMT(' ', 2, "d", range(1, timeptr->tm_mday, 31)); | ||||
| 			FMT(' ', 2, "d", range(1, vtm->mday, 31)); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'r':	/* time as %I:%M:%S %p */ | ||||
|  | @ -604,12 +648,12 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 
 | ||||
| #ifdef SUNOS_EXT | ||||
| 		case 'k':	/* hour, 24-hour clock, blank pad */ | ||||
| 			i = range(0, timeptr->tm_hour, 23); | ||||
| 			i = range(0, vtm->hour, 23); | ||||
| 			FMT(' ', 2, "d", i); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'l':	/* hour, 12-hour clock, 1 - 12, blank pad */ | ||||
| 			i = range(0, timeptr->tm_hour, 23); | ||||
| 			i = range(0, vtm->hour, 23); | ||||
| 			if (i == 0) | ||||
| 				i = 12; | ||||
| 			else if (i > 12) | ||||
|  | @ -621,25 +665,16 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 
 | ||||
| #ifdef VMS_EXT | ||||
| 		case 'v':	/* date as dd-bbb-YYYY */ | ||||
| 			w = snprintf(s, endp - s, "%2d-%3.3s-%4ld", | ||||
| 				     range(1, timeptr->tm_mday, 31), | ||||
| 				     months_l[range(0, timeptr->tm_mon, 11)], | ||||
| 				     timeptr->tm_year + 1900L); | ||||
| 			if (w < 0) goto err; | ||||
| 			for (i = 3; i < 6; i++) | ||||
| 				if (ISLOWER(s[i])) | ||||
| 					s[i] = TOUPPER(s[i]); | ||||
| 			s += w; | ||||
| 			STRFTIME("%e-%^b-%4Y"); | ||||
| 			continue; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #ifdef POSIX2_DATE | ||||
| 		case 'C': | ||||
| 			FMT('0', 2, "ld", (timeptr->tm_year + 1900L) / 100); | ||||
|                         FMTV('0', 2, "d", div(vtm->year, INT2FIX(100))); | ||||
| 			continue; | ||||
| 
 | ||||
| 
 | ||||
| 		case 'E': | ||||
| 			/* POSIX locale extensions, ignored for now */ | ||||
| 			flags |= BIT_OF(LOCALE_E); | ||||
|  | @ -650,12 +685,12 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 			goto again; | ||||
| 
 | ||||
| 		case 'V':	/* week of year according ISO 8601 */ | ||||
| 			FMT('0', 2, "d", iso8601wknum(timeptr)); | ||||
| 			FMT('0', 2, "d", iso8601wknum_v(vtm)); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'u': | ||||
| 		/* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */ | ||||
| 			FMT('0', 1, "d", timeptr->tm_wday == 0 ? 7 : timeptr->tm_wday); | ||||
| 			FMT('0', 1, "d", vtm->wday == 0 ? 7 : vtm->wday); | ||||
| 			continue; | ||||
| #endif	/* POSIX2_DATE */ | ||||
| 
 | ||||
|  | @ -671,19 +706,25 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 			 * 53, that week is in last year. | ||||
| 			 * Otherwise, it's this year. | ||||
| 			 */ | ||||
| 			w = iso8601wknum(timeptr); | ||||
| 			if (timeptr->tm_mon == 11 && w == 1) | ||||
| 				y = 1900L + timeptr->tm_year + 1; | ||||
| 			else if (timeptr->tm_mon == 0 && w >= 52) | ||||
| 				y = 1900L + timeptr->tm_year - 1; | ||||
| 			else | ||||
| 				y = 1900L + timeptr->tm_year; | ||||
|                         { | ||||
|                                 VALUE yv = vtm->year; | ||||
|                                 w = iso8601wknum_v(vtm); | ||||
|                                 if (vtm->mon == 12 && w == 1) | ||||
|                                         yv = add(yv, INT2FIX(1)); | ||||
|                                 else if (vtm->mon == 1 && w >= 52) | ||||
|                                         yv = sub(yv, INT2FIX(1)); | ||||
| 
 | ||||
|                                 if (*format == 'G') { | ||||
|                                         FMTV('0', 1, "d", yv); | ||||
|                                 } | ||||
|                                 else { | ||||
|                                         yv = mod(yv, INT2FIX(100)); | ||||
|                                         y = FIX2LONG(yv); | ||||
|                                         FMT('0', 2, "ld", y); | ||||
|                                 } | ||||
|                                 continue; | ||||
|                         } | ||||
| 
 | ||||
| 			if (*format == 'G') | ||||
| 				FMT('0', 1, "ld", y); | ||||
| 			else | ||||
| 				FMT('0', 2, "ld", y % 100); | ||||
| 			continue; | ||||
| #endif /* ISO_DATE_EXT */ | ||||
| 
 | ||||
| 
 | ||||
|  | @ -703,35 +744,46 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept | |||
| 			w = 9; | ||||
| 		subsec: | ||||
| 			{ | ||||
| 				long n = ts->tv_nsec; | ||||
|                                 VALUE subsec = mod(timev, INT2FIX(1)); | ||||
|                                 int ww; | ||||
|                                 long n; | ||||
| 
 | ||||
| 				if (precision <= 0) { | ||||
| 				    precision = w; | ||||
| 				} | ||||
| 				NEEDS(precision); | ||||
| 				if (precision < w) { | ||||
| 					snprintf(tbuf, w + 1, "%.*ld", w, n); | ||||
| 					memcpy(s, tbuf, precision); | ||||
| 				} | ||||
| 				else { | ||||
| 					snprintf(s, endp - s, "%.*ld", w, n); | ||||
| 					memset(s + w, '0', precision - w); | ||||
| 				} | ||||
| 				s += precision; | ||||
| 
 | ||||
|                                 ww = precision; | ||||
|                                 while (9 <= ww) { | ||||
|                                         subsec = mul(subsec, INT2FIX(1000000000)); | ||||
|                                         ww -= 9; | ||||
|                                 } | ||||
|                                 n = 1; | ||||
|                                 for (; 0 < ww; ww--) | ||||
|                                         n *= 10; | ||||
|                                 if (n != 1) | ||||
|                                         subsec = mul(subsec, INT2FIX(n)); | ||||
|                                 subsec = div(subsec, INT2FIX(1)); | ||||
| 
 | ||||
|                                 if (FIXNUM_P(subsec)) { | ||||
|                                         int l; | ||||
|                                         l = snprintf(s, endp - s, "%0*ld", precision, FIX2LONG(subsec)); | ||||
|                                         s += precision; | ||||
|                                 } | ||||
|                                 else { | ||||
|                                         VALUE args[2], result; | ||||
|                                         size_t l; | ||||
|                                         args[0] = INT2FIX(precision); | ||||
|                                         args[1] = subsec; | ||||
|                                         result = rb_str_format(2, args, rb_str_new2("%0*d")); | ||||
|                                         l = strlcpy(s, StringValueCStr(result), endp-s); | ||||
|                                         s += precision; | ||||
|                                 } | ||||
| 			} | ||||
| 			continue; | ||||
| 
 | ||||
| 		case 'F':	/*  Equivalent to %Y-%m-%d */ | ||||
| 			{ | ||||
| 				int mon, mday; | ||||
| 				mon = range(0, timeptr->tm_mon, 11) + 1; | ||||
| 				mday = range(1, timeptr->tm_mday, 31); | ||||
| 				i = snprintf(s, endp - s, "%ld-%02d-%02d", | ||||
| 					     1900L + timeptr->tm_year, mon, mday); | ||||
| 				if (i < 0) | ||||
| 					goto err; | ||||
| 				s += i; | ||||
| 			} | ||||
| 			STRFTIME("%Y-%m-%d"); | ||||
| 			continue; | ||||
| 
 | ||||
| 		case '-': | ||||
|  | @ -820,6 +872,31 @@ isleap(long year) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void | ||||
| vtm2tm_noyear(const struct vtm *vtm, struct tm *result) | ||||
| { | ||||
|     struct tm tm; | ||||
| 
 | ||||
|     /* for isleap() in iso8601wknum.  +100 is -1900 (mod 400). */ | ||||
|     tm.tm_year = FIX2INT(mod(vtm->year, INT2FIX(400))) + 100; | ||||
| 
 | ||||
|     tm.tm_mon = vtm->mon-1; | ||||
|     tm.tm_mday = vtm->mday; | ||||
|     tm.tm_hour = vtm->hour; | ||||
|     tm.tm_min = vtm->min; | ||||
|     tm.tm_sec = vtm->sec; | ||||
|     tm.tm_wday = vtm->wday; | ||||
|     tm.tm_yday = vtm->yday-1; | ||||
|     tm.tm_isdst = vtm->isdst; | ||||
| #if defined(HAVE_STRUCT_TM_TM_GMTOFF) | ||||
|     tm.tm_gmtoff = NUM2LONG(vtm->utc_offset); | ||||
| #endif | ||||
| #if defined(HAVE_TM_ZONE) | ||||
|     tm.tm_zone = vtm->zone; | ||||
| #endif | ||||
|     *result = tm; | ||||
| } | ||||
| 
 | ||||
| #ifdef POSIX2_DATE | ||||
| /* iso8601wknum --- compute week number according to ISO 8601 */ | ||||
| 
 | ||||
|  | @ -935,6 +1012,15 @@ iso8601wknum(const struct tm *timeptr) | |||
| 
 | ||||
| 	return weeknum; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| iso8601wknum_v(const struct vtm *vtm) | ||||
| { | ||||
|         struct tm tm; | ||||
|         vtm2tm_noyear(vtm, &tm); | ||||
|         return iso8601wknum(&tm); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /* weeknumber --- figure how many weeks into the year */ | ||||
|  | @ -966,6 +1052,14 @@ weeknumber(const struct tm *timeptr, int firstweekday) | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| weeknumber_v(const struct vtm *vtm, int firstweekday) | ||||
| { | ||||
|         struct tm tm; | ||||
|         vtm2tm_noyear(vtm, &tm); | ||||
|         return weeknumber(&tm, firstweekday); | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
| /* ADR --- I'm loathe to mess with ado's code ... */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| require 'test/unit' | ||||
| require 'rational' | ||||
| require 'delegate' | ||||
| require 'timeout' | ||||
| require 'delegate' | ||||
| 
 | ||||
|  | @ -101,31 +102,47 @@ class TestTime < Test::Unit::TestCase | |||
|   end | ||||
| 
 | ||||
|   def test_at | ||||
|     assert_equal(100000, Time.at("0.1").usec) | ||||
|     assert_equal(10000, Time.at("0.01").usec) | ||||
|     assert_equal(1000, Time.at("0.001").usec) | ||||
|     assert_equal(100, Time.at("0.0001").usec) | ||||
|     assert_equal(10, Time.at("0.00001").usec) | ||||
|     assert_equal(1, Time.at("0.000001").usec) | ||||
|     assert_equal(100000000, Time.at("0.1").nsec) | ||||
|     assert_equal(10000000, Time.at("0.01").nsec) | ||||
|     assert_equal(1000000, Time.at("0.001").nsec) | ||||
|     assert_equal(100000, Time.at("0.0001").nsec) | ||||
|     assert_equal(10000, Time.at("0.00001").nsec) | ||||
|     assert_equal(1000, Time.at("0.000001").nsec) | ||||
|     assert_equal(100, Time.at("0.0000001").nsec) | ||||
|     assert_equal(10, Time.at("0.00000001").nsec) | ||||
|     assert_equal(1, Time.at("0.000000001").nsec) | ||||
|     assert_equal(100000, Time.at(0.1).usec) | ||||
|     assert_equal(10000, Time.at(0.01).usec) | ||||
|     assert_equal(1000, Time.at(0.001).usec) | ||||
|     assert_equal(100, Time.at(0.0001).usec) | ||||
|     assert_equal(10, Time.at(0.00001).usec) | ||||
|     assert_equal(1, Time.at(0.000001).usec) | ||||
|     assert_equal(3, Time.at(0.000003).usec) | ||||
|     assert_equal(100000000, Time.at(0.1).nsec) | ||||
|     assert_equal(10000000, Time.at(0.01).nsec) | ||||
|     assert_equal(1000000, Time.at(0.001).nsec) | ||||
|     assert_equal(100000, Time.at(0.0001).nsec) | ||||
|     assert_equal(10000, Time.at(0.00001).nsec) | ||||
|     assert_equal(1000, Time.at(0.000001).nsec) | ||||
|     assert_equal(100, Time.at(0.0000001).nsec) | ||||
|     assert_equal(3000, Time.at(0.000003).nsec) | ||||
|     assert_equal(199, Time.at(0.0000002).nsec) | ||||
|     assert_equal(10, Time.at(0.00000001).nsec) | ||||
|     assert_equal(1, Time.at(0.000000001).nsec) | ||||
| 
 | ||||
|     assert_equal(0, Time.at(1e-10).nsec) | ||||
|     assert_equal(0, Time.at(4e-10).nsec) | ||||
|     assert_equal(1, Time.at(6e-10).nsec) | ||||
|     assert_equal(0, Time.at(6e-10).nsec) | ||||
|     assert_equal(1, Time.at(14e-10).nsec) | ||||
|     assert_equal(2, Time.at(16e-10).nsec) | ||||
|     assert_equal(1, Time.at(16e-10).nsec) | ||||
|     if negative_time_t? | ||||
|       assert_equal(0, Time.at(-1e-10).nsec) | ||||
|       assert_equal(0, Time.at(-4e-10).nsec) | ||||
|       assert_equal(999999999, Time.at(-1e-10).nsec) | ||||
|       assert_equal(999999999, Time.at(-4e-10).nsec) | ||||
|       assert_equal(999999999, Time.at(-6e-10).nsec) | ||||
|       assert_equal(999999999, Time.at(-14e-10).nsec) | ||||
|       assert_equal(999999998, Time.at(-14e-10).nsec) | ||||
|       assert_equal(999999998, Time.at(-16e-10).nsec) | ||||
|     end | ||||
|   end | ||||
|  | @ -142,7 +159,7 @@ class TestTime < Test::Unit::TestCase | |||
|   end | ||||
| 
 | ||||
|   def test_utc_subsecond | ||||
|     assert_equal(100000, Time.utc(2007,1,1,0,0,1.1).usec) | ||||
|     assert_equal(500000, Time.utc(2007,1,1,0,0,1.5).usec) | ||||
|     assert_equal(100000, Time.utc(2007,1,1,0,0,Rational(11,10)).usec) | ||||
|   end | ||||
| 
 | ||||
|  | @ -189,14 +206,14 @@ class TestTime < Test::Unit::TestCase | |||
| 
 | ||||
|   def test_at3 | ||||
|     assert_equal(T2000, Time.at(T2000)) | ||||
|     assert_raise(RangeError) do | ||||
|       Time.at(2**31-1, 1_000_000) | ||||
|       Time.at(2**63-1, 1_000_000) | ||||
|     end | ||||
|     assert_raise(RangeError) do | ||||
|       Time.at(-2**31, -1_000_000) | ||||
|       Time.at(-2**63, -1_000_000) | ||||
|     end | ||||
| #    assert_raise(RangeError) do | ||||
| #      Time.at(2**31-1, 1_000_000) | ||||
| #      Time.at(2**63-1, 1_000_000) | ||||
| #    end | ||||
| #    assert_raise(RangeError) do | ||||
| #      Time.at(-2**31, -1_000_000) | ||||
| #      Time.at(-2**63, -1_000_000) | ||||
| #    end | ||||
|   end | ||||
| 
 | ||||
|   def test_utc_or_local | ||||
|  | @ -216,10 +233,15 @@ class TestTime < Test::Unit::TestCase | |||
|     end | ||||
|     assert_raise(ArgumentError) { Time.gm(2000, 1, 1, 0, 0, -(2**31), :foo, :foo) } | ||||
|     o = Object.new | ||||
|     def o.divmod(x); nil; end | ||||
|     def o.to_r; nil; end | ||||
|     assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) } | ||||
|     def o.divmod(x); [-1, 0]; end | ||||
|     assert_raise(ArgumentError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) } | ||||
|     def o.to_r; ""; end | ||||
|     assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) } | ||||
|     def o.to_r; Rational(11); end | ||||
|     assert_equal(11, Time.gm(2000, 1, 1, 0, 0, o).sec) | ||||
|     o = Object.new | ||||
|     def o.to_int; 10; end | ||||
|     assert_equal(10, Time.gm(2000, 1, 1, 0, 0, o).sec) | ||||
|     assert_raise(ArgumentError) { Time.gm(2000, 13) } | ||||
| 
 | ||||
|     t = Time.local(2000) | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ class YAML_Unit_Tests < Test::Unit::TestCase | |||
| 	# Make a time with the time zone | ||||
| 	# | ||||
| 	def mktime( year, mon, day, hour, min, sec, usec, zone = "Z" ) | ||||
|         usec = usec.to_s.to_f * 1000000 | ||||
|         usec = Rational(usec.to_s) * 1000000 | ||||
| 		val = Time::utc( year.to_i, mon.to_i, day.to_i, hour.to_i, min.to_i, sec.to_i, usec ) | ||||
| 		if zone != "Z" | ||||
| 			hour = zone[0,3].to_i * 3600 | ||||
|  |  | |||
							
								
								
									
										19
									
								
								timev.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								timev.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| #ifndef RUBY_TIMEV_H | ||||
| #define RUBY_TIMEV_H | ||||
| 
 | ||||
| struct vtm { | ||||
|     VALUE year; /* 2000 for example.  Integer. */ | ||||
|     int mon; /* 1..12 */ | ||||
|     int mday; /* 1..31 */ | ||||
|     int hour; /* 0..23 */ | ||||
|     int min; /* 0..59 */ | ||||
|     int sec; /* 0..60 */ | ||||
|     VALUE subsec; /* 0 <= subsec < 1.  possibly Rational. */ | ||||
|     VALUE utc_offset; /* -3600 as -01:00 for example.  possibly Rational. */ | ||||
|     int wday; /* 0:Sunday, 1:Monday, ..., 6:Saturday */ | ||||
|     int yday; /* 1..366 */ | ||||
|     int isdst; /* 0:StandardTime 1:DayLightSavingTime */ | ||||
|     const char *zone; /* "JST", "EST", "EDT", etc. */ | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 akr
						akr