@@ -141,19 +141,22 @@ fn all_digits(s: &str) -> bool {
141141}
142142
143143/// Convert a two-digit year string to the corresponding number.
144+ ///
145+ /// `s` must be of length two or more. The last two bytes of `s` are
146+ /// assumed to be the two digits of the year.
144147fn get_year ( s : & str ) -> u8 {
145- // Pre-condition: s.len() >= 2
146148 let bytes = s. as_bytes ( ) ;
147- let y1 = bytes[ 0 ] - b'0' ;
148- let y2 = bytes[ 1 ] - b'0' ;
149+ let n = bytes. len ( ) ;
150+ let y1 = bytes[ n - 2 ] - b'0' ;
151+ let y2 = bytes[ n - 1 ] - b'0' ;
149152 10 * y1 + y2
150153}
151154
152155/// Whether the first filename should be interpreted as a timestamp.
153156fn is_first_filename_timestamp (
154157 reference : Option < & OsString > ,
155158 date : Option < & str > ,
156- timestamp : Option < & String > ,
159+ timestamp : & Option < String > ,
157160 files : & [ & String ] ,
158161) -> bool {
159162 match std:: env:: var ( "_POSIX2_VERSION" ) {
@@ -180,6 +183,18 @@ fn is_first_filename_timestamp(
180183 }
181184}
182185
186+ /// Cycle the last two characters to the beginning of the string.
187+ ///
188+ /// `s` must have length at least two.
189+ fn shr2 ( s : & str ) -> String {
190+ let n = s. len ( ) ;
191+ let ( a, b) = s. split_at ( n - 2 ) ;
192+ let mut result = String :: with_capacity ( n) ;
193+ result. push_str ( b) ;
194+ result. push_str ( a) ;
195+ result
196+ }
197+
183198#[ uucore:: main]
184199pub fn uumain ( args : impl uucore:: Args ) -> UResult < ( ) > {
185200 let matches = uu_app ( ) . try_get_matches_from ( args) ?;
@@ -204,19 +219,23 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
204219 . get_one :: < String > ( options:: sources:: DATE )
205220 . map ( |date| date. to_owned ( ) ) ;
206221
207- let mut timestamp = matches. get_one :: < String > ( options:: sources:: TIMESTAMP ) ;
222+ let mut timestamp = matches
223+ . get_one :: < String > ( options:: sources:: TIMESTAMP )
224+ . map ( |t| t. to_owned ( ) ) ;
208225
209- if is_first_filename_timestamp ( reference, date. as_deref ( ) , timestamp, & filenames) {
210- let head = filenames[ 0 ] ;
211- let tail = & filenames[ 1 ..] ;
212- timestamp = Some ( head) ;
213- filenames = tail. to_vec ( ) ;
226+ if is_first_filename_timestamp ( reference, date. as_deref ( ) , & timestamp, & filenames) {
227+ timestamp = if filenames[ 0 ] . len ( ) == 10 {
228+ Some ( shr2 ( filenames[ 0 ] ) )
229+ } else {
230+ Some ( filenames[ 0 ] . to_string ( ) )
231+ } ;
232+ filenames = filenames[ 1 ..] . to_vec ( ) ;
214233 }
215234
216235 let source = if let Some ( reference) = reference {
217236 Source :: Reference ( PathBuf :: from ( reference) )
218237 } else if let Some ( ts) = timestamp {
219- Source :: Timestamp ( parse_timestamp ( ts) ?)
238+ Source :: Timestamp ( parse_timestamp ( & ts) ?)
220239 } else {
221240 Source :: Now
222241 } ;
0 commit comments