diff --git a/src/lib-sieve/plugins/date/tst-date.c b/src/lib-sieve/plugins/date/tst-date.c
index ce6e0885d5b74c90a447219fd5abb8e986f059af..e719318ee5c306cb5cf695a25d405f1a961ebeea 100644
--- a/src/lib-sieve/plugins/date/tst-date.c
+++ b/src/lib-sieve/plugins/date/tst-date.c
@@ -390,7 +390,7 @@ static int tst_date_operation_execute
 	string_t *date_part = NULL, *zone = NULL;
 	struct sieve_stringlist *hdr_list = NULL, *hdr_value_list;
 	struct sieve_stringlist *value_list, *key_list;
-	bool zone_specified = FALSE;
+	bool zone_specified = FALSE, zone_literal = TRUE;
 	int time_zone;
 	int match, ret;
 	
@@ -414,6 +414,8 @@ static int tst_date_operation_execute
 				if ( (ret=sieve_opr_string_read_data
 					(renv, &oprnd, address, "zone", &zone)) <= 0 )
 					return ret;
+
+				zone_literal = sieve_operand_is_string_literal(&oprnd);
 			}
 
 			zone_specified = TRUE;
@@ -435,26 +437,29 @@ static int tst_date_operation_execute
 	if ( (ret=sieve_opr_string_read(renv, address, "date-part", &date_part)) 
 		<= 0 )
 		return ret;
-		
+
 	/* Read key-list */
 	if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list))
 		<= 0 )
 		return ret;
-	
+
 	/* Determine what time zone to use in the result */
 	if ( !zone_specified ) {
 		time_zone = EXT_DATE_TIMEZONE_LOCAL;
 	} else if ( zone == NULL ) {
 		time_zone = EXT_DATE_TIMEZONE_ORIGINAL;
 	} else if ( !ext_date_parse_timezone(str_c(zone), &time_zone) ) {
-		/* FIXME: warn about parse failures */
+		if ( !zone_literal )
+			sieve_runtime_warning(renv, NULL, 
+				"specified :zone argument '%s' is not a valid timezone "
+				"(using local zone)", str_sanitize(str_c(zone), 40));
 		time_zone = EXT_DATE_TIMEZONE_LOCAL;
 	}
 
-	/* 
+	/*
 	 * Perform test 
 	 */
-	
+
 	if ( sieve_operation_is(op, date_operation) ) {
 	
 		sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "date test");
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index d0899159097e9ad8d69b89e9a13f3a81524f2cad..4f3b206fabc58e83ffb631afe12ca2925c6c46b6 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -546,7 +546,7 @@ bool sieve_opr_string_dump_ex
 		return FALSE;
 	}
 
-	*literal_r = sieve_operand_is(&operand, string_operand);	
+	*literal_r = sieve_operand_is_string_literal(&operand);
 
 	return sieve_opr_string_dump_data(denv, &operand, address, field_name);
 } 
@@ -601,7 +601,7 @@ int sieve_opr_string_read_ex
 		<= 0 )
 		return ret;
 
-	*literal_r = sieve_operand_is(&operand, string_operand);
+	*literal_r = sieve_operand_is_string_literal(&operand);
 
 	return sieve_opr_string_read_data(renv, &operand, address, field_name, str_r);
 }
diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h
index 5f768f5e7ee7ecadf4c6742b7b89bb4bc3a5dd2e..30c7b8880f04003c30086770ed6b922b447a096e 100644
--- a/src/lib-sieve/sieve-code.h
+++ b/src/lib-sieve/sieve-code.h
@@ -231,6 +231,12 @@ static inline bool sieve_operand_is_string
 		operand->def->class == &string_class );
 }
 
+static inline bool sieve_operand_is_string_literal
+(const struct sieve_operand *operand)
+{
+	return ( operand != NULL && sieve_operand_is(operand, string_operand) );
+}
+
 /* String list */
 
 void sieve_opr_stringlist_emit_start