11/* -----------------------------------------------------------------------
22 * formatting.c
33 *
4- * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.66 2003/08/04 23:59:38 tgl Exp $
4+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.67 2003/08/25 16:13:27 tgl Exp $
55 *
66 *
77 * Portions Copyright (c) 1999-2003, PostgreSQL Global Development Group
@@ -880,6 +880,8 @@ static intseq_search(char *name, char **array, int type, int max, int *len);
880880static int dch_global (int arg ,char * inout ,int suf ,int flag ,FormatNode * node ,void * data );
881881static int dch_time (int arg ,char * inout ,int suf ,int flag ,FormatNode * node ,void * data );
882882static int dch_date (int arg ,char * inout ,int suf ,int flag ,FormatNode * node ,void * data );
883+ static void do_to_timestamp (text * date_txt ,text * fmt ,
884+ struct tm * tm ,fsec_t * fsec );
883885static char * fill_str (char * str ,int c ,int max );
884886static FormatNode * NUM_cache (int len ,NUMDesc * Num ,char * pars_str ,bool * shouldFree );
885887static char * int_to_roman (int number );
@@ -2901,21 +2903,65 @@ to_timestamp(PG_FUNCTION_ARGS)
29012903{
29022904text * date_txt = PG_GETARG_TEXT_P (0 );
29032905text * fmt = PG_GETARG_TEXT_P (1 );
2904-
29052906Timestamp result ;
2907+ int tz ;
2908+ struct tm tm ;
2909+ fsec_t fsec ;
2910+
2911+ do_to_timestamp (date_txt ,fmt ,& tm ,& fsec );
2912+
2913+ tz = DetermineLocalTimeZone (& tm );
2914+
2915+ if (tm2timestamp (& tm ,fsec ,& tz ,& result )!= 0 )
2916+ ereport (ERROR ,
2917+ (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
2918+ errmsg ("timestamp out of range" )));
2919+
2920+ PG_RETURN_TIMESTAMP (result );
2921+ }
2922+
2923+ /* ----------
2924+ * TO_DATE
2925+ *Make Date from date_str which is formated at argument 'fmt'
2926+ * ----------
2927+ */
2928+ Datum
2929+ to_date (PG_FUNCTION_ARGS )
2930+ {
2931+ text * date_txt = PG_GETARG_TEXT_P (0 );
2932+ text * fmt = PG_GETARG_TEXT_P (1 );
2933+ DateADT result ;
2934+ struct tm tm ;
2935+ fsec_t fsec ;
2936+
2937+ do_to_timestamp (date_txt ,fmt ,& tm ,& fsec );
2938+
2939+ result = date2j (tm .tm_year ,tm .tm_mon ,tm .tm_mday )- POSTGRES_EPOCH_JDATE ;
2940+
2941+ PG_RETURN_DATEADT (result );
2942+ }
2943+
2944+ /*
2945+ * do_to_timestamp: shared code for to_timestamp and to_date
2946+ *
2947+ * Parse the 'date_txt' according to 'fmt', return results as a struct tm
2948+ * and fractional seconds.
2949+ */
2950+ static void
2951+ do_to_timestamp (text * date_txt ,text * fmt ,
2952+ struct tm * tm ,fsec_t * fsec )
2953+ {
29062954FormatNode * format ;
29072955TmFromChar tmfc ;
2908-
29092956bool incache ;
29102957char * str ;
29112958char * date_str ;
29122959int len ,
2913- date_len ,
2914- tz = 0 ;
2915- struct tm tm ;
2916- fsec_t fsec = 0 ;
2960+ date_len ;
2961+
2962+ ZERO_tm ( tm ) ;
2963+ * fsec = 0 ;
29172964
2918- ZERO_tm (& tm );
29192965ZERO_tmfc (& tmfc );
29202966
29212967len = VARSIZE (fmt )- VARHDRSZ ;
@@ -3004,15 +3050,15 @@ to_timestamp(PG_FUNCTION_ARGS)
30043050{
30053051int x = tmfc .ssss ;
30063052
3007- tm . tm_hour = x /3600 ;
3053+ tm -> tm_hour = x /3600 ;
30083054x %=3600 ;
3009- tm . tm_min = x /60 ;
3055+ tm -> tm_min = x /60 ;
30103056x %=60 ;
3011- tm . tm_sec = x ;
3057+ tm -> tm_sec = x ;
30123058}
30133059
30143060if (tmfc .cc )
3015- tm . tm_year = (tmfc .cc - 1 )* 100 ;
3061+ tm -> tm_year = (tmfc .cc - 1 )* 100 ;
30163062
30173063if (tmfc .ww )
30183064tmfc .ddd = (tmfc .ww - 1 )* 7 + 1 ;
@@ -3021,79 +3067,79 @@ to_timestamp(PG_FUNCTION_ARGS)
30213067tmfc .dd = (tmfc .w - 1 )* 7 + 1 ;
30223068
30233069if (tmfc .ss )
3024- tm . tm_sec = tmfc .ss ;
3070+ tm -> tm_sec = tmfc .ss ;
30253071if (tmfc .mi )
3026- tm . tm_min = tmfc .mi ;
3072+ tm -> tm_min = tmfc .mi ;
30273073if (tmfc .hh )
3028- tm . tm_hour = tmfc .hh ;
3074+ tm -> tm_hour = tmfc .hh ;
30293075
30303076if (tmfc .pm || tmfc .am )
30313077{
3032- if (tm . tm_hour < 1 || tm . tm_hour > 12 )
3078+ if (tm -> tm_hour < 1 || tm -> tm_hour > 12 )
30333079ereport (ERROR ,
30343080(errcode (ERRCODE_INVALID_DATETIME_FORMAT ),
30353081errmsg ("AM/PM hour must be between 1 and 12" )));
30363082
3037- if (tmfc .pm && tm . tm_hour < 12 )
3038- tm . tm_hour += 12 ;
3083+ if (tmfc .pm && tm -> tm_hour < 12 )
3084+ tm -> tm_hour += 12 ;
30393085
3040- else if (tmfc .am && tm . tm_hour == 12 )
3041- tm . tm_hour = 0 ;
3086+ else if (tmfc .am && tm -> tm_hour == 12 )
3087+ tm -> tm_hour = 0 ;
30423088}
30433089
30443090switch (tmfc .q )
30453091{
30463092case 1 :
3047- tm . tm_mday = 1 ;
3048- tm . tm_mon = 1 ;
3093+ tm -> tm_mday = 1 ;
3094+ tm -> tm_mon = 1 ;
30493095break ;
30503096case 2 :
3051- tm . tm_mday = 1 ;
3052- tm . tm_mon = 4 ;
3097+ tm -> tm_mday = 1 ;
3098+ tm -> tm_mon = 4 ;
30533099break ;
30543100case 3 :
3055- tm . tm_mday = 1 ;
3056- tm . tm_mon = 7 ;
3101+ tm -> tm_mday = 1 ;
3102+ tm -> tm_mon = 7 ;
30573103break ;
30583104case 4 :
3059- tm . tm_mday = 1 ;
3060- tm . tm_mon = 10 ;
3105+ tm -> tm_mday = 1 ;
3106+ tm -> tm_mon = 10 ;
30613107break ;
30623108}
30633109
30643110if (tmfc .year )
3065- tm . tm_year = tmfc .year ;
3111+ tm -> tm_year = tmfc .year ;
30663112
30673113if (tmfc .bc )
30683114{
3069- if (tm . tm_year > 0 )
3070- tm . tm_year = - (tm . tm_year - 1 );
3115+ if (tm -> tm_year > 0 )
3116+ tm -> tm_year = - (tm -> tm_year - 1 );
30713117else
30723118ereport (ERROR ,
30733119(errcode (ERRCODE_INVALID_DATETIME_FORMAT ),
30743120errmsg ("inconsistent use of year %04d and \"BC\"" ,
3075- tm . tm_year )));
3121+ tm -> tm_year )));
30763122}
30773123
30783124if (tmfc .j )
3079- j2date (tmfc .j ,& tm . tm_year ,& tm . tm_mon ,& tm . tm_mday );
3125+ j2date (tmfc .j ,& tm -> tm_year ,& tm -> tm_mon ,& tm -> tm_mday );
30803126
30813127if (tmfc .iw )
3082- isoweek2date (tmfc .iw ,& tm . tm_year ,& tm . tm_mon ,& tm . tm_mday );
3128+ isoweek2date (tmfc .iw ,& tm -> tm_year ,& tm -> tm_mon ,& tm -> tm_mday );
30833129
30843130if (tmfc .d )
3085- tm . tm_wday = tmfc .d ;
3131+ tm -> tm_wday = tmfc .d ;
30863132if (tmfc .dd )
3087- tm . tm_mday = tmfc .dd ;
3133+ tm -> tm_mday = tmfc .dd ;
30883134if (tmfc .ddd )
3089- tm . tm_yday = tmfc .ddd ;
3135+ tm -> tm_yday = tmfc .ddd ;
30903136if (tmfc .mm )
3091- tm . tm_mon = tmfc .mm ;
3137+ tm -> tm_mon = tmfc .mm ;
30923138
30933139/*
30943140 * we don't ignore DDD
30953141 */
3096- if (tmfc .ddd && (tm . tm_mon <=1 || tm . tm_mday <=1 ))
3142+ if (tmfc .ddd && (tm -> tm_mon <=1 || tm -> tm_mday <=1 ))
30973143{
30983144/* count mday and mon from yday */
30993145int * y ,
@@ -3103,65 +3149,41 @@ to_timestamp(PG_FUNCTION_ARGS)
31033149{31 ,59 ,90 ,120 ,151 ,181 ,212 ,243 ,273 ,304 ,334 ,365 ,0 },
31043150{31 ,60 ,91 ,121 ,152 ,182 ,213 ,244 ,274 ,305 ,335 ,366 ,0 }};
31053151
3106- if (!tm . tm_year )
3152+ if (!tm -> tm_year )
31073153ereport (ERROR ,
31083154(errcode (ERRCODE_INVALID_DATETIME_FORMAT ),
31093155errmsg ("cannot convert yday without year information" )));
31103156
3111- y = ysum [isleap (tm . tm_year )];
3157+ y = ysum [isleap (tm -> tm_year )];
31123158
31133159for (i = 0 ;i <=11 ;i ++ )
31143160{
3115- if (tm . tm_yday < y [i ])
3161+ if (tm -> tm_yday < y [i ])
31163162break ;
31173163}
3118- if (tm . tm_mon <=1 )
3119- tm . tm_mon = i + 1 ;
3164+ if (tm -> tm_mon <=1 )
3165+ tm -> tm_mon = i + 1 ;
31203166
3121- if (tm . tm_mday <=1 )
3122- tm . tm_mday = i == 0 ?tm . tm_yday :
3123- tm . tm_yday - y [i - 1 ];
3167+ if (tm -> tm_mday <=1 )
3168+ tm -> tm_mday = i == 0 ?tm -> tm_yday :
3169+ tm -> tm_yday - y [i - 1 ];
31243170}
31253171
31263172#ifdef HAVE_INT64_TIMESTAMP
31273173if (tmfc .ms )
3128- fsec += tmfc .ms * 1000 ;
3174+ * fsec += tmfc .ms * 1000 ;
31293175if (tmfc .us )
3130- fsec += tmfc .us ;
3176+ * fsec += tmfc .us ;
31313177#else
31323178if (tmfc .ms )
3133- fsec += (double )tmfc .ms /1000 ;
3179+ * fsec += (double )tmfc .ms /1000 ;
31343180if (tmfc .us )
3135- fsec += (double )tmfc .us /1000000 ;
3181+ * fsec += (double )tmfc .us /1000000 ;
31363182#endif
31373183
3138- /* -------------------------------------------------------------- */
3139-
3140- DEBUG_TM (& tm );
3141- tz = DetermineLocalTimeZone (& tm );
3142-
3143- if (tm2timestamp (& tm ,fsec ,& tz ,& result )!= 0 )
3144- ereport (ERROR ,
3145- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3146- errmsg ("timestamp out of range" )));
3147-
3148- PG_RETURN_TIMESTAMP (result );
3184+ DEBUG_TM (tm );
31493185}
31503186
3151- /* ----------
3152- * TO_DATE
3153- *Make Date from date_str which is formated at argument 'fmt'
3154- * ----------
3155- */
3156- Datum
3157- to_date (PG_FUNCTION_ARGS )
3158- {
3159- /*
3160- * Quick hack: since our inputs are just like to_timestamp, hand over
3161- * the whole input info struct...
3162- */
3163- return DirectFunctionCall1 (timestamptz_date ,to_timestamp (fcinfo ));
3164- }
31653187
31663188/**********************************************************************
31673189 *the NUMBER version part