18
18
import itertools
19
19
import csv
20
20
21
- from pandas .tseries .period import PeriodIndex
21
+ from pandas .tseries .period import PeriodIndex , DatetimeIndex
22
22
23
23
docstring_to_string = """
24
24
Parameters
@@ -850,7 +850,7 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
850
850
cols = None , header = True , index = True , index_label = None ,
851
851
mode = 'w' , nanRep = None , encoding = None , quoting = None ,
852
852
line_terminator = '\n ' , chunksize = None , engine = None ,
853
- tupleize_cols = False , quotechar = '"' ):
853
+ tupleize_cols = False , quotechar = '"' , date_format = None ):
854
854
855
855
self .engine = engine # remove for 0.13
856
856
self .obj = obj
@@ -877,6 +877,8 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
877
877
878
878
self .line_terminator = line_terminator
879
879
880
+ self .date_format = date_format
881
+
880
882
#GH3457
881
883
if not self .obj .columns .is_unique and engine == 'python' :
882
884
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,
893
895
894
896
if cols is not None :
895
897
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 )
897
900
else :
898
901
cols = list (cols )
899
902
self .obj = self .obj .loc [:,cols ]
@@ -902,7 +905,8 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
902
905
# and make sure sure cols is just a list of labels
903
906
cols = self .obj .columns
904
907
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 )
906
910
else :
907
911
cols = list (cols )
908
912
@@ -923,6 +927,9 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
923
927
if isinstance (obj .index , PeriodIndex ):
924
928
self .data_index = obj .index .to_timestamp ()
925
929
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
+
926
933
self .nlevels = getattr (self .data_index , 'nlevels' , 1 )
927
934
if not index :
928
935
self .nlevels = 0
@@ -931,15 +938,10 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
931
938
# invoked by df.to_csv(engine=python)
932
939
def _helper_csv (self , writer , na_rep = None , cols = None ,
933
940
header = True , index = True ,
934
- index_label = None , float_format = None ):
941
+ index_label = None , float_format = None , date_format = None ):
935
942
if cols is None :
936
943
cols = self .columns
937
944
938
- series = {}
939
- for k , v in compat .iteritems (self .obj ._series ):
940
- series [k ] = v .values
941
-
942
-
943
945
has_aliases = isinstance (header , (tuple , list , np .ndarray ))
944
946
if has_aliases or header :
945
947
if index :
@@ -981,10 +983,34 @@ def _helper_csv(self, writer, na_rep=None, cols=None,
981
983
encoded_cols = list (cols )
982
984
writer .writerow (encoded_cols )
983
985
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
+
984
996
data_index = self .obj .index
997
+
985
998
if isinstance (self .obj .index , PeriodIndex ):
986
999
data_index = self .obj .index .to_timestamp ()
987
1000
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
+
988
1014
nlevels = getattr (data_index , 'nlevels' , 1 )
989
1015
for j , idx in enumerate (data_index ):
990
1016
row_fields = []
@@ -1000,8 +1026,8 @@ def _helper_csv(self, writer, na_rep=None, cols=None,
1000
1026
1001
1027
if float_format is not None and com .is_float (val ):
1002
1028
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 )
1005
1031
1006
1032
row_fields .append (val )
1007
1033
@@ -1031,7 +1057,7 @@ def save(self):
1031
1057
self ._helper_csv (self .writer , na_rep = self .na_rep ,
1032
1058
float_format = self .float_format , cols = self .cols ,
1033
1059
header = self .header , index = self .index ,
1034
- index_label = self .index_label )
1060
+ index_label = self .index_label , date_format = self . date_format )
1035
1061
1036
1062
else :
1037
1063
self ._save ()
@@ -1150,13 +1176,16 @@ def _save_chunk(self, start_i, end_i):
1150
1176
slicer = slice (start_i ,end_i )
1151
1177
for i in range (len (self .blocks )):
1152
1178
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
+
1154
1182
for i , item in enumerate (b .items ):
1155
1183
1156
1184
# self.data is a preallocated list
1157
1185
self .data [self .column_map [b ][i ]] = d [i ]
1158
1186
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 )
1160
1189
1161
1190
lib .write_csv_rows (self .data , ix , self .nlevels , self .cols , self .writer )
1162
1191
0 commit comments