1818import itertools
1919import csv
2020
21- from pandas .tseries .period import PeriodIndex
21+ from pandas .tseries .period import PeriodIndex , DatetimeIndex
2222
2323docstring_to_string = """
2424 Parameters
@@ -850,7 +850,7 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
850850 cols = None , header = True , index = True , index_label = None ,
851851 mode = 'w' , nanRep = None , encoding = None , quoting = None ,
852852 line_terminator = '\n ' , chunksize = None , engine = None ,
853- tupleize_cols = False , quotechar = '"' ):
853+ tupleize_cols = False , quotechar = '"' , date_format = None ):
854854
855855 self .engine = engine # remove for 0.13
856856 self .obj = obj
@@ -877,6 +877,8 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
877877
878878 self .line_terminator = line_terminator
879879
880+ self .date_format = date_format
881+
880882 #GH3457
881883 if not self .obj .columns .is_unique and engine == 'python' :
882884 msg = "columns.is_unique == False not supported with engine='python'"
@@ -893,7 +895,8 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
893895
894896 if cols is not None :
895897 if isinstance (cols ,Index ):
896- cols = cols .to_native_types (na_rep = na_rep ,float_format = float_format )
898+ cols = cols .to_native_types (na_rep = na_rep ,float_format = float_format ,
899+ date_format = date_format )
897900 else :
898901 cols = list (cols )
899902 self .obj = self .obj .loc [:,cols ]
@@ -902,7 +905,8 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
902905 # and make sure sure cols is just a list of labels
903906 cols = self .obj .columns
904907 if isinstance (cols ,Index ):
905- cols = cols .to_native_types (na_rep = na_rep ,float_format = float_format )
908+ cols = cols .to_native_types (na_rep = na_rep ,float_format = float_format ,
909+ date_format = date_format )
906910 else :
907911 cols = list (cols )
908912
@@ -923,6 +927,9 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
923927 if isinstance (obj .index , PeriodIndex ):
924928 self .data_index = obj .index .to_timestamp ()
925929
930+ if isinstance (self .data_index , DatetimeIndex ) and date_format is not None :
931+ self .data_index = Index ([x .strftime (date_format ) if notnull (x ) else '' for x in self .data_index ])
932+
926933 self .nlevels = getattr (self .data_index , 'nlevels' , 1 )
927934 if not index :
928935 self .nlevels = 0
@@ -931,15 +938,10 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
931938 # invoked by df.to_csv(engine=python)
932939 def _helper_csv (self , writer , na_rep = None , cols = None ,
933940 header = True , index = True ,
934- index_label = None , float_format = None ):
941+ index_label = None , float_format = None , date_format = None ):
935942 if cols is None :
936943 cols = self .columns
937944
938- series = {}
939- for k , v in compat .iteritems (self .obj ._series ):
940- series [k ] = v .values
941-
942-
943945 has_aliases = isinstance (header , (tuple , list , np .ndarray ))
944946 if has_aliases or header :
945947 if index :
@@ -981,10 +983,34 @@ def _helper_csv(self, writer, na_rep=None, cols=None,
981983 encoded_cols = list (cols )
982984 writer .writerow (encoded_cols )
983985
986+ if date_format is None :
987+ date_formatter = lambda x : lib .Timestamp (x )._repr_base
988+ else :
989+ def strftime_with_nulls (x ):
990+ x = lib .Timestamp (x )
991+ if notnull (x ):
992+ return x .strftime (date_format )
993+
994+ date_formatter = lambda x : strftime_with_nulls (x )
995+
984996 data_index = self .obj .index
997+
985998 if isinstance (self .obj .index , PeriodIndex ):
986999 data_index = self .obj .index .to_timestamp ()
9871000
1001+ if isinstance (data_index , DatetimeIndex ) and date_format is not None :
1002+ data_index = Index ([date_formatter (x ) for x in data_index ])
1003+
1004+ values = self .obj .copy ()
1005+ values .index = data_index
1006+ values .columns = values .columns .to_native_types (na_rep = na_rep ,float_format = float_format ,
1007+ date_format = date_format )
1008+ values = values [cols ]
1009+
1010+ series = {}
1011+ for k , v in compat .iteritems (values ._series ):
1012+ series [k ] = v .values
1013+
9881014 nlevels = getattr (data_index , 'nlevels' , 1 )
9891015 for j , idx in enumerate (data_index ):
9901016 row_fields = []
@@ -1000,8 +1026,8 @@ def _helper_csv(self, writer, na_rep=None, cols=None,
10001026
10011027 if float_format is not None and com .is_float (val ):
10021028 val = float_format % val
1003- elif isinstance (val , np .datetime64 ):
1004- val = lib . Timestamp (val ). _repr_base
1029+ elif isinstance (val , ( np .datetime64 , lib . Timestamp ) ):
1030+ val = date_formatter (val )
10051031
10061032 row_fields .append (val )
10071033
@@ -1031,7 +1057,7 @@ def save(self):
10311057 self ._helper_csv (self .writer , na_rep = self .na_rep ,
10321058 float_format = self .float_format , cols = self .cols ,
10331059 header = self .header , index = self .index ,
1034- index_label = self .index_label )
1060+ index_label = self .index_label , date_format = self . date_format )
10351061
10361062 else :
10371063 self ._save ()
@@ -1150,13 +1176,16 @@ def _save_chunk(self, start_i, end_i):
11501176 slicer = slice (start_i ,end_i )
11511177 for i in range (len (self .blocks )):
11521178 b = self .blocks [i ]
1153- d = b .to_native_types (slicer = slicer , na_rep = self .na_rep , float_format = self .float_format )
1179+ d = b .to_native_types (slicer = slicer , na_rep = self .na_rep ,
1180+ float_format = self .float_format , date_format = self .date_format )
1181+
11541182 for i , item in enumerate (b .items ):
11551183
11561184 # self.data is a preallocated list
11571185 self .data [self .column_map [b ][i ]] = d [i ]
11581186
1159- ix = data_index .to_native_types (slicer = slicer , na_rep = self .na_rep , float_format = self .float_format )
1187+ ix = data_index .to_native_types (slicer = slicer , na_rep = self .na_rep ,
1188+ float_format = self .float_format , date_format = self .date_format )
11601189
11611190 lib .write_csv_rows (self .data , ix , self .nlevels , self .cols , self .writer )
11621191
0 commit comments