Reputation: 101
I used yyyy-MM-dd'T'HH:mm:ss.SSSXXX
format string with icu::SimpleDateFormat.
Though it works for date-time strings with fractional digits. Examples:
2016-03-31T15:04:32.049Z
2016-03-31T15:04:32.05Z
2016-03-31T15:04:32.3Z
It doesn't parse strings without fractional second (e.g. 2016-03-31T15:08:51Z
), returning an error code U_ILLEGAL_ARGUMENT_ERROR.
I tried some other format combinations to no avail: some fail with an error code, others ignore milliseconds.
Does ICU even support parsing of an optional fractional second?
Upvotes: 4
Views: 1902
Reputation: 794
Going through ICU's documentation, I did not find any way how to input optional part in pattern specification.
However, this problem can be solved in many different ways on the application level. One of such ways (simplified) is using multiple datetime parsers as follows:
#include <iostream>
#include <vector>
#include "unicode/datefmt.h"
#include "unicode/smpdtfmt.h"
int main() {
UErrorCode err(U_ZERO_ERROR);
UnicodeString patternWithMilliseconds("yyyy-MM-dd'T'hh:mm:ss.SSSXXX");
UnicodeString patternPlane("yyyy-MM-dd'T'hh:mm:ssX");
// init ICU parsers
std::vector<SimpleDateFormat*> parsers = {
new SimpleDateFormat(patternWithMilliseconds, err),
new SimpleDateFormat(patternPlane, err)
};
// get dates to convert
std::vector<UnicodeString> dates = {
UnicodeString("2016-03-31T15:04:32.049Z"),
UnicodeString("2017-10-30T15:05:33Z"),
};
SimpleDateFormat resultFormatter(patternWithMilliseconds, err);
for(const auto& date : dates) {
UDate parsedDate;
UnicodeString result;
std::string resultConverted;
for(const auto& parser : parsers) {
err = U_ZERO_ERROR;
parsedDate = parser->parse(date, err);
if (err <= 0) break;
}
resultFormatter.format(parsedDate, result);
result.toUTF8String(resultConverted);
std::cout << resultConverted << std::endl;
}
for(auto& parser : parsers) {
delete parser;
}
return 0;
}
Upvotes: 1