I have a string want to convert to date, but below code,
that str
print out show Optional(2016-04-25 17:00:16 +0000)
I want to know how to show exact what it is like Optional(2016-04-26T03:00:16.047)
var str = "2016-04-26T03:00:16.047"
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"//this your string date format
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let date = dateFormatter.dateFromString(str)
print(date) //Optional(2016-04-25 17:00:16 +0000)
Related
I'm using rust and chrono::NaiveDate to read an Excel file with date column type in it.
The date itself is formatted with "dd-mm-yyyy"
I can read the excel file and found out that the reader I use (https://docs.rs/calamine/latest/calamine/) returns float value for the date
A documentation in Microsoft site states that the date starts from January 1st, 1900
The float value in it corresponds to this dates:
date_value (FLOAT)
real value (in dd-mm-yyyy)
44198
02-01-2021
44199
03-01-2021
44200
04-01-2021
etc...
Basically I need a function or crate that can calculate month, date, and years from the float value I get. I have no clue on how to do this.
Below is my code
let data_type = calamine::DataType::deserialize(deserializer);
match data_type {
Ok(DataType::Error(_)) => {
Ok(None)
}
Ok(DataType::String(date_str)) => {
let msg = "Failed to convert Date. Wrong format or empty.";
let val = NaiveDate::parse_from_str(&date_str, DATE_FORMAT)
.map_err(|_| Error::custom(msg))?;
Ok(Some(val))
}
Ok(DataType::Float(dt)) => {
println!("this is float!!!");
println!("dt: {}", dt); // dt is a float number that count the number of days from January 1st 1900
let year = ? // what should I do here ?
let month = ?
let day = ?
let val = NaiveDate::from_ymd_opt(year, month, day)
Ok(None)
}
_ => {
Ok(None)
}
}
calamine has a dates feature that adds a DataType.as_date() method returning an Option<chrono::NaiveDate>.
There are also DataType.as_datetime() and DataType.as_time().
I don't know why it isn't documented, so use carefully.
At least, the method code could be a starting point for your own implementation.
A possible solution regarding my comment would be:
use chrono::{Duration, NaiveDate};
fn main() {
let start = NaiveDate::from_ymd_opt(1900, 1, 1).expect("DATE");
let date = start.checked_add_signed(Duration::days(44198)); // date_value
println!("{}", date.unwrap());
}
Playground
How to convert a String to a chrono::DateTime or chrono::NaiveDateTime
And what does the ParseError(NotEnough) or ParseError(TooShort) mean?
When converting a String into a Chrono object you have to know what parts the input format of the string has.
The parts are: Date, Time, TimeZone
Examples:
"2020-04-12" => Date = NaiveDate
"22:10" => Time = NaiveTime
"2020-04-12 22:10:57" => Date + Time = NaiveDateTime
"2020-04-12 22:10:57+02:00" => Date + Time + TimeZone = DateTime<Tz>
The ParseError(NotEnough) shows up when there is not enough information to fill out the whole object. For example the date, time or timezone is missing.
When the formats doesn't match the string you get a ParseError(TooShort) or ParseError(Invalid) error.
Specification for string format e.g. "%Y-%m-%d %H:%M:%S": https://docs.rs/chrono/latest/chrono/format/strftime/index.html
RFC2822 = Date + Time + TimeZone
To convert a RFC2822 string use the parse_from_rfc2822(..) function.
let date_str = "Tue, 1 Jul 2003 10:52:37 +0200";
let datetime = DateTime::parse_from_rfc2822(date_str).unwrap();
RFC3339 = Date + Time + TimeZone
To convert a RFC3339 or ISO 8601 string use the parse_from_rfc3339(..) function.
let date_str = "2020-04-12T22:10:57+02:00";
// convert the string into DateTime<FixedOffset>
let datetime = DateTime::parse_from_rfc3339(date_str).unwrap();
// convert the string into DateTime<Utc> or other timezone
let datetime_utc = datetime.with_timezone(&Utc);
Date + Time + Timezone (other or non-standard)
To convert other DateTime strings use the parse_from_str(..) function.
let date_str = "2020-04-12 22:10:57 +02:00";
let datetime = DateTime::parse_from_str(date_str, "%Y-%m-%d %H:%M:%S %z").unwrap();
Date + Time
When you do not have a TimeZone you need to use NaiveDateTime. This object does not store a timezone:
let date_str = "2020-04-12 22:10:57";
let naive_datetime = NaiveDateTime::parse_from_str(date_str, "%Y-%m-%d %H:%M:%S").unwrap();
Date
If we were parsing a date (with no time) we can store it in a NaiveDate. This object does not store time or a timezone:
let date_str = "2020-04-12";
let naive_date = NaiveDate::parse_from_str(date_str, "%Y-%m-%d").unwrap();
Time
If we were parsing a time (with no date) we can store it in a NaiveTime. This object does not store a date or a timezone:
let time_str = "22:10:57";
let naive_time = NaiveTime::parse_from_str(time_str, "%H:%M:%S").unwrap();
Add Date, Time and/or Timezone
If we have some string and want to add more information we can change the type. But you have to provide this information yourself.
let date_str = "2020-04-12";
// From string to a NaiveDate
let naive_date = NaiveDate::parse_from_str(date_str, "%Y-%m-%d").unwrap();
// Add some default time to convert it into a NaiveDateTime
let naive_datetime: NaiveDateTime = naive_date.and_hms(0,0,0);
// Add a timezone to the object to convert it into a DateTime<UTC>
let datetime_utc = DateTime::<Utc>::from_utc(naive_datetime, Utc);
Example code playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d2b83b3980a5f8fb2e798271766b4541
Starting Swift 4, I have one unit test that starts to fail. It seems that the timezone data I get is quite incorrect.
The following working code:
let f1 = DateFormatter()
f1.dateFormat = "yyyy-MM-dd"
let d = f1.date(from: "1999-01-01")
let f2 = DateFormatter()
f2.dateFormat = "Z"
f2.string(from: d)
I'm in America/Los_Angeles, so I get -0800
If I swap 1999 to 1500 with this code:
let f1 = DateFormatter()
f1.dateFormat = "yyyy-MM-dd"
let d = f1.date(from: "1500-01-01")
let f2 = DateFormatter()
f2.dateFormat = "Z"
f2.string(from: d)
I get -075258
Is this even a correct/allowed value? How can I get something valid for usage in a ISO 8601 ?
I have this String 2015-02-17T08:53:22.9170000+00:00 and I want to converted to NSdate.
The prefered format to print is hh:mm:ss-dd-mm-yyyy.
Try this one
let string = "2015-02-17T08:53:22.9170000+00:00"
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSz"
if let date = formatter.dateFromString(string) {
//Now you can format what ever you want, like
formatter.dateFormat = "hh:mm:ss-dd-mm-yyyy"
print(formatter.stringFromDate(date))
}
let stringWithDate = "2015-07-16T6:08:32.000Z"
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let dateComponents = NSDateComponents()
dateComponents.year = 2015
dateComponents.month = 7
dateComponents.day = 16
dateComponents.hour = 6
dateComponents.minute = 8
dateComponents.second = 32
let dateFromDateFormatter = dateFormatter.dateFromString(stringWithDate) //"Jul 16, 2015, 8:08 AM"
let dateFromDateComponents = NSCalendar.currentCalendar().dateFromComponents(dateComponents)! //"Jul 16, 2015, 6:08 AM"
dateFromDateFormatter == dateFromDateComponents //false
Why these dates are not the same?
After some digging, I have found a solution:
NSDateFormatter includes information about NSTimeZone (Z at the end of Sting) while NSDateComponents doesn't. So we need to simple inform dateComponents about NSTimeZone:
dateComponents.timeZone = NSTimeZone(abbreviation: "UTC")
The output dates are now the same.
Adding the same information to dateFormatter:
dateFormatter.timeZone = NSTimeZone(abbreviation: "UTC")
doesn't change anything, because there is information about NSTimeZone yet.