@@ -4,22 +4,22 @@ use crate::{
4
4
components:: { calendar:: Calendar , Instant } ,
5
5
iso:: { IsoDate , IsoDateTime , IsoTime } ,
6
6
options:: {
7
- ArithmeticOverflow , DifferenceOperation , DifferenceSettings , ResolvedRoundingOptions ,
8
- RoundingOptions , TemporalUnit ,
7
+ ArithmeticOverflow , DifferenceOperation , DifferenceSettings , DisplayCalendar ,
8
+ ResolvedRoundingOptions , RoundingOptions , TemporalUnit , ToStringRoundingOptions ,
9
9
} ,
10
- parsers:: parse_date_time,
10
+ parsers:: { parse_date_time, IxdtfStringBuilder } ,
11
11
temporal_assert, Sign , TemporalError , TemporalResult , TemporalUnwrap , TimeZone ,
12
12
} ;
13
-
13
+ use alloc :: string :: String ;
14
14
use core:: { cmp:: Ordering , str:: FromStr } ;
15
- use tinystr:: TinyAsciiStr ;
16
15
17
16
use super :: {
18
17
calendar:: { CalendarDateLike , GetTemporalCalendar } ,
19
18
duration:: normalized:: { NormalizedDurationRecord , NormalizedTimeDuration } ,
20
19
timezone:: NeverProvider ,
21
20
Duration , PartialDate , PartialTime , PlainDate , PlainTime ,
22
21
} ;
22
+ use tinystr:: TinyAsciiStr ;
23
23
24
24
/// A partial PlainDateTime record
25
25
#[ derive( Debug , Default , Clone ) ]
@@ -38,6 +38,15 @@ pub struct PlainDateTime {
38
38
calendar : Calendar ,
39
39
}
40
40
41
+ impl core:: fmt:: Display for PlainDateTime {
42
+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
43
+ let ixdtf_str = self
44
+ . to_ixdtf_string ( ToStringRoundingOptions :: default ( ) , DisplayCalendar :: Auto )
45
+ . expect ( "ixdtf default configuration should not fail." ) ;
46
+ f. write_str ( & ixdtf_str)
47
+ }
48
+ }
49
+
41
50
impl Ord for PlainDateTime {
42
51
fn cmp ( & self , other : & Self ) -> Ordering {
43
52
self . iso . cmp ( & other. iso )
@@ -619,6 +628,28 @@ impl PlainDateTime {
619
628
620
629
Ok ( Self :: new_unchecked ( result, self . calendar . clone ( ) ) )
621
630
}
631
+
632
+ pub fn to_ixdtf_string (
633
+ & self ,
634
+ options : ToStringRoundingOptions ,
635
+ display_calendar : DisplayCalendar ,
636
+ ) -> TemporalResult < String > {
637
+ let resolved_options = options. resolve ( ) ?;
638
+ let result = self
639
+ . iso
640
+ . round ( ResolvedRoundingOptions :: from_to_string_options (
641
+ & resolved_options,
642
+ ) ) ?;
643
+ if !result. is_within_limits ( ) {
644
+ return Err ( TemporalError :: range ( ) . with_message ( "DateTime is not within valid limits." ) ) ;
645
+ }
646
+ let ixdtf_string = IxdtfStringBuilder :: default ( )
647
+ . with_date ( result. date )
648
+ . with_time ( result. time , resolved_options. precision )
649
+ . with_calendar ( self . calendar . identifier ( ) , display_calendar)
650
+ . build ( ) ;
651
+ Ok ( ixdtf_string)
652
+ }
622
653
}
623
654
624
655
// ==== Trait impls ====
@@ -682,9 +713,10 @@ mod tests {
682
713
} ,
683
714
iso:: { IsoDate , IsoDateTime , IsoTime } ,
684
715
options:: {
685
- DifferenceSettings , RoundingIncrement , RoundingOptions , TemporalRoundingMode ,
686
- TemporalUnit ,
716
+ DifferenceSettings , DisplayCalendar , RoundingIncrement , RoundingOptions ,
717
+ TemporalRoundingMode , TemporalUnit , ToStringRoundingOptions ,
687
718
} ,
719
+ parsers:: Precision ,
688
720
primitive:: FiniteF64 ,
689
721
TemporalResult ,
690
722
} ;
@@ -1098,4 +1130,156 @@ mod tests {
1098
1130
. unwrap ( ) ;
1099
1131
assert_datetime ( result, ( 1976 , 11 , 18 , 14 , 23 , 30 , 123 , 456 , 790 ) ) ;
1100
1132
}
1133
+
1134
+ // Mapped from fractionaldigits-number.js
1135
+ #[ test]
1136
+ fn to_string_precision_digits ( ) {
1137
+ let few_seconds =
1138
+ PlainDateTime :: try_new ( 1976 , 2 , 4 , 5 , 3 , 1 , 0 , 0 , 0 , Calendar :: default ( ) ) . unwrap ( ) ;
1139
+ let zero_seconds =
1140
+ PlainDateTime :: try_new ( 1976 , 11 , 18 , 15 , 23 , 0 , 0 , 0 , 0 , Calendar :: default ( ) ) . unwrap ( ) ;
1141
+ let whole_seconds =
1142
+ PlainDateTime :: try_new ( 1976 , 11 , 18 , 15 , 23 , 30 , 0 , 0 , 0 , Calendar :: default ( ) ) . unwrap ( ) ;
1143
+ let subseconds =
1144
+ PlainDateTime :: try_new ( 1976 , 11 , 18 , 15 , 23 , 30 , 123 , 400 , 0 , Calendar :: default ( ) )
1145
+ . unwrap ( ) ;
1146
+
1147
+ let options = ToStringRoundingOptions {
1148
+ precision : Precision :: Digit ( 0 ) ,
1149
+ smallest_unit : None ,
1150
+ rounding_mode : None ,
1151
+ } ;
1152
+ assert_eq ! (
1153
+ & few_seconds
1154
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1155
+ . unwrap( ) ,
1156
+ "1976-02-04T05:03:01" ,
1157
+ "pads parts with 0"
1158
+ ) ;
1159
+
1160
+ let options = ToStringRoundingOptions {
1161
+ precision : Precision :: Digit ( 0 ) ,
1162
+ smallest_unit : None ,
1163
+ rounding_mode : None ,
1164
+ } ;
1165
+ assert_eq ! (
1166
+ & subseconds
1167
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1168
+ . unwrap( ) ,
1169
+ "1976-11-18T15:23:30" ,
1170
+ "truncates 4 decimal places to 0"
1171
+ ) ;
1172
+
1173
+ let options = ToStringRoundingOptions {
1174
+ precision : Precision :: Digit ( 2 ) ,
1175
+ smallest_unit : None ,
1176
+ rounding_mode : None ,
1177
+ } ;
1178
+ assert_eq ! (
1179
+ & zero_seconds
1180
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1181
+ . unwrap( ) ,
1182
+ "1976-11-18T15:23:00.00" ,
1183
+ "pads zero seconds to 2 decimal places"
1184
+ ) ;
1185
+ let options = ToStringRoundingOptions {
1186
+ precision : Precision :: Digit ( 2 ) ,
1187
+ smallest_unit : None ,
1188
+ rounding_mode : None ,
1189
+ } ;
1190
+
1191
+ assert_eq ! (
1192
+ & whole_seconds
1193
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1194
+ . unwrap( ) ,
1195
+ "1976-11-18T15:23:30.00" ,
1196
+ "pads whole seconds to 2 decimal places"
1197
+ ) ;
1198
+ let options = ToStringRoundingOptions {
1199
+ precision : Precision :: Digit ( 2 ) ,
1200
+ smallest_unit : None ,
1201
+ rounding_mode : None ,
1202
+ } ;
1203
+ assert_eq ! (
1204
+ & subseconds
1205
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1206
+ . unwrap( ) ,
1207
+ "1976-11-18T15:23:30.12" ,
1208
+ "truncates 4 decimal places to 2"
1209
+ ) ;
1210
+
1211
+ let options = ToStringRoundingOptions {
1212
+ precision : Precision :: Digit ( 3 ) ,
1213
+ smallest_unit : None ,
1214
+ rounding_mode : None ,
1215
+ } ;
1216
+ assert_eq ! (
1217
+ & subseconds
1218
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1219
+ . unwrap( ) ,
1220
+ "1976-11-18T15:23:30.123" ,
1221
+ "truncates 4 decimal places to 3"
1222
+ ) ;
1223
+
1224
+ let options = ToStringRoundingOptions {
1225
+ precision : Precision :: Digit ( 6 ) ,
1226
+ smallest_unit : None ,
1227
+ rounding_mode : None ,
1228
+ } ;
1229
+ assert_eq ! (
1230
+ & subseconds
1231
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1232
+ . unwrap( ) ,
1233
+ "1976-11-18T15:23:30.123400" ,
1234
+ "pads 4 decimal places to 6"
1235
+ ) ;
1236
+ let options = ToStringRoundingOptions {
1237
+ precision : Precision :: Digit ( 7 ) ,
1238
+ smallest_unit : None ,
1239
+ rounding_mode : None ,
1240
+ } ;
1241
+ assert_eq ! (
1242
+ & zero_seconds
1243
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1244
+ . unwrap( ) ,
1245
+ "1976-11-18T15:23:00.0000000" ,
1246
+ "pads zero seconds to 7 decimal places"
1247
+ ) ;
1248
+ let options = ToStringRoundingOptions {
1249
+ precision : Precision :: Digit ( 7 ) ,
1250
+ smallest_unit : None ,
1251
+ rounding_mode : None ,
1252
+ } ;
1253
+ assert_eq ! (
1254
+ & whole_seconds
1255
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1256
+ . unwrap( ) ,
1257
+ "1976-11-18T15:23:30.0000000" ,
1258
+ "pads whole seconds to 7 decimal places"
1259
+ ) ;
1260
+ let options = ToStringRoundingOptions {
1261
+ precision : Precision :: Digit ( 7 ) ,
1262
+ smallest_unit : None ,
1263
+ rounding_mode : None ,
1264
+ } ;
1265
+ assert_eq ! (
1266
+ & subseconds
1267
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1268
+ . unwrap( ) ,
1269
+ "1976-11-18T15:23:30.1234000" ,
1270
+ "pads 4 decimal places to 7"
1271
+ ) ;
1272
+ let options = ToStringRoundingOptions {
1273
+ precision : Precision :: Digit ( 9 ) ,
1274
+ smallest_unit : None ,
1275
+ rounding_mode : None ,
1276
+ } ;
1277
+ assert_eq ! (
1278
+ & subseconds
1279
+ . to_ixdtf_string( options, DisplayCalendar :: Auto )
1280
+ . unwrap( ) ,
1281
+ "1976-11-18T15:23:30.123400000" ,
1282
+ "pads 4 decimal places to 9"
1283
+ ) ;
1284
+ }
1101
1285
}
0 commit comments