Foundation in macOS 10.12 has a new class, NSISO8601DateFormatter, which claims to be able to parse ISO-8601, but I'm having trouble understanding how to use it.
It takes a .formatOptions, which it says is used for parsing, too. Isn't the whole point of ISO-8601 that it's an unambiguous format?
For example, this works:
let f = ISO8601DateFormatter()
f.formatOptions = [.withFullDate]
f.date(from: "2018-11-26") // a Date
but this ignores the time:
let f = ISO8601DateFormatter()
f.formatOptions = [.withFullDate]
f.date(from: "2018-11-26T18:07:13Z") // a Date but wrong
If I add .withFullTime, this works, but then the first example fails.
How do I parse ISO-8601 with NSISO8601DateFormatter? Do I need to first pre-parse it on my own to figure out what sub-format of ISO-8601 it uses?
Related
I have the following datetime helper method that converts a UTC-zoned Java 8 Date into a datetime string:
public static String dateTimeString(Date date) {
return date.toInstant().atZone(ZoneId.of("UTC")).toLocalDateTime().toString();
}
The desired result is to always have the resultant String be formatted as:
YYYY-MM-dd'T'HH:mm:ss'Z'
Problem is, Java 8 LocalTime#toString() intentionally strips off time components that are zero. So for instance if I have a Date instance that represents June 8, 2018 at 12:35:00 UTC. Then the output of this method above is: 2018-06-08'T'12:35'Z'. Whereas I want it to contain any zeroed-out second/minute/hour components (e.g. 2018-06-08'T'12:35:00'Z').
Any ideas?
private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssX");
public static String dateTimeString(Date date) {
return date.toInstant().atOffset(ZoneOffset.UTC).format(formatter);
}
Just use a fixed format pattern string to get your desired format. Let’s try it:
System.out.println(dateTimeString(new Date(0)));
System.out.println(dateTimeString(new Date(1_524_560_255_555L)));
This prints:
1970-01-01T00:00:00Z
2018-04-24T08:57:35Z
In the first example hours, minutes and seconds are printed even if they are 0.
In the second example milliseoncds are omitted even when they are non-zero (you see that the milliseconds value I specified ends in 555).
All of this said, the output conforms to the ISO 8601 format no matter if you have 2018-06-08T12:35Z, 2018-06-08T12:35:00Z or even 2018-06-08T12:35:00.000000000Z. So you may want to check once more whether leaving out the second works for your purpose before you take the trouble of defining your own formatter.
Link: Wikipedia article: ISO 8601
I don't see why you portray the default output to have its letters enclosed in single quotes when Java's actual output instead looks like 2018-06-08T12:35Z, but anyway, here's the code that produces it as desired, with no omissions:
final LocalDateTime ldt = LocalDateTime.of(2018, 6, 8, 12, 35, 0);
final ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.of("Z"));
final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'''T'''HH:mm:ss''X''", Locale.US);
System.err.println(dtf.format(zdt));
Output:
2018-06-08'T'12:35:00'Z'
Personally, I'd probably prefer a format like this, containing the millis, giving time zone information not requiring additional knowledge from the user, and not having imho superfluous characters:
FORMAT: "yyyy-MM-dd HH:mm:ss'.'SSS Z"
OUTPUT: 2018-06-08 12:35:12.345 +0200
It appears that there is no out of the box solution. The simplest way would be to write your own class that extends DateTimeFormatter and override method public String format(TemporalAccessor temporal) where you would call the original method and then if needed modify the output String. See the flags 'Z' for formatter. If that flag is present then you will need to modify the original output.
I've seen that you can use an ".isValid()" function to check that a given string is in a date format:
moment('2007-05-05', 'YYYY-MM-DD', true).isValid()
But is there a way to confirm that the format is correct? For example:
'YYYY-MM-DD' should return true, but
'YYYY-MM-DDsadsadl' should return false since the characters at the end of the string aren't valid DateTime chars.
We're working on a tool that allows a user to input an existing date format, and then a second input to enter the desired format, but we need validation to ensure the string can properly parse and convert, but they aren't entering a specific date.
The application must accept any and all possible date formats.
Use the following function to validate your format.
validFormat = function(inputFormat){
var validation = moment(moment('2017-06-17').format(inputFormat), inputFormat).inspect();
if(validation.indexOf('invalid') < 0)
return true;
else
return false;
}
Do spend some time to understand this. This simply does a reverse verification using inspect(). The date 2017-06-17 can be replaced by any valid date.
This Moment Js Docs will help you identify the valid formats.
Just make a call to this function as
validFormat('YYYY MM DD')
const getIsValid = inputFormat => moment(moment().format(inputFormat), inputFormat).isValid()
Explanation:
moment().format(inputFormat) - Create a date string from the current time from that format
This is then wrapped with moment() to make that string a moment date object, defining the format to parse it with. Finally we call the isValid() property on that moment date object. This ensures we are able to both create and parse a moment with our custom format.
Did like below,
LocalDateTime currentUTCTime = LocalDateTime.now(ZoneId.of("UTC"));
String reqPattern = currentUTCTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS"));
System.out.println("Required pattern: " + reqPattern);
GregorianCalendar calendar = GregorianCalendar.from(currentUTCTime.atZone(ZoneId.systemDefault()));
XMLGregorianCalendar xcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar);
System.out.println("But Showing As :" + xcal);
I want the output as 2015-06-18 11:59:15:135, but when i set the xcal to
a XML tag which takes XMLGregorianCalender, it shows like 2015-06-18T11:59:15.135+05:30.
How can i remove the +05:30 portion?
Use this code:
LocalDateTime currentUTCTime = LocalDateTime.now(); // using system timezone
String iso = currentUTCTime.toString();
if (currentUTCTime.getSecond() == 0 && currentUTCTime.getNano() == 0) {
iso += ":00"; // necessary hack because the second part is not optional in XML
}
XMLGregorianCalendar xml =
DatatypeFactory.newInstance().newXMLGregorianCalendar(iso);
Explanation:
The code makes use of the given factory method expecting a lexicographical representation of a local timestamp in ISO-8601-format. And since a LocalDateTime does not refer to any timezone, its output via toString() cannot contain a timezone offset. Result: XMLGregorianCalendar considers the timezone offset as "not set".
Correction:
The original code did not especially bother about the ISO-variant of formatted output of currentUTCTime.toString(). However, the java.time-API produces an output without seconds or nanoseconds if those parts are equal to zero. This is perfectly legal in ISO, but the W3C-consortium has made the second part non-optional. And the class XMLGregorianCalendar closely follows this deviating spec. Therefore the shown hack above using simple string concatenation in this special edge case. Thanks a lot to #Dave's comment. By the way, using currentUTCTime.format(DateTimeFormatter.ISO_DATE_TIME) as suggested in this comment is also possible (instead of the shown hack).
I am using the following code to get the hour and minute in d3.js
e.time=e.time.substring(12,19);
var timeformat=d3.time.format("%H:%M").parse;
e.time2=timeformat(e.time);
console.log(e.time2);
But I am getting null in output. My e.time contains following pattern of value
2015-03-29T20:32:24Z
e.time.substring(12,19) returns 20:32:24.
What is the mistake I am doing?
You need to do 2 things here:
Parse the string 20:32:24, to a date. For that use:
var timeformat=d3.time.format("%H:%M:%S").parse;
Format the Date, returning a string in the valid format )in this case hh:mm:
var hoursandminsformat=d3.time.format("%H:%M");
Fiddle here: http://jsfiddle.net/henbox/mwvvuazz/
A better approach, rather than using e.time.substring(12,19);, would be just to parse the full date object using:
var ISO8601format=d3.time.format("%Y-%m-%dT%H:%M:%SZ")
and then
var fomatted_time = hoursandminsformat(ISO8601format.parse("2015-03-29T20:32:24Z"));
How to get current format of the locale so that i can Format datetime with the format i get.
Means if i got the format then i can format that.
DateTime.Now.ToString(format);
This i am doing in visual studio with xamarin for creating Android application from C#.net.
Please help me for getting me the format.
Thanks & Regards
Parvez
You can use the culture info as formatter.
var d = DateTime.Now;
System.Diagnostics.Debug.WriteLine(
d.ToString(System.Globalization.CultureInfo.CurrentCulture));
System.Diagnostics.Debug.WriteLine(
d.ToString(System.Globalization.CultureInfo.CurrentUICulture));
try building the date format that you require, example below:
var now = DateTime.Now;
string newdateformat = string.Format("{0:00}/{1:00}/{2:0000}", now.Month, now.Day, now.Year);
If I understood your question correctly you want to format a DateTime to a string representation depending on the settings of the device (the locale).
You can do it like so:
var javaDate = new Date(YourDateTime.ToUnixTime()*1000);
var dt = DateFormat.DateTimeInstance;
SomeTextView.Text = string.Format("DateTime is: {0}", dt.Format(javaDate));
Notice that I used an extension method ToUnixTime() which converts DateTime to an Epoch time (also known as unix time) representation. You can find it easily even here on Stackoverflow.
(you can use DateFormat.DateInstance if you don't want the time part of the string)
Hope it helps.