Epoch to Date during the decode - swift

I have the following json object.
{"date" : 1596304900, "name" : "registration"}
I have the following struct
struct Classroom : Codable{
let date : Int
let name : String
}
As you see in the json object, date is actually epoch time and want to convert it to human readable date during the decode operation. I wonder how it needs to be done during the decode.

Make your date a Date instead of an Int, and use a JSONDecoder with its date decoding strategy set to the epoch decoder:
https://developer.apple.com/documentation/foundation/jsondecoder/datedecodingstrategy/secondssince1970
Everything will happen correctly as if by magic. (In the example you've given, the date will turn out to be August 1, 2020, at 18:01:40 GMT.)
Note that this will not be "human-readable"; it will be a date. You don't store human-readable; you show human readable. You deal with that in the interface only, with a formatter.

Related

How can we send Date object to Rest Api in swiftui?

Currently in my DTO class, I am declaring a type like this.
var transferDate : Date?
private enum CodingKeys: String, CodingKey {
case transferDate = "TransferDate"
}
override func encode(to encoder: Encoder) throws{
try super.encode(to:encode)
try container.encode(transferDate, forKey: .transferDate)
}
In my view, I am assigning Date like this
Dto.transferDate = self.Date
while debugging I see this in debug window
(Date) <unavailable; try printing with "vo" or "po"
Any help would be appreciated.
Thanks
You shouldn't have to do anything custom for Dates. As I recall, by default the system encodes dates as a Double like the one returned by Date.timeIntervalSinceReferenceDate().
If you're writing the RESTFUL API, you should be able to write it to handle that date format.
If you need "internet dates" (date strings in the standard format that includes an offset from UTC) you would need to specify that when setting up your encoder.

How can I convert a String to a Dictionary type in Swift?

I have a String
example:
"['name': 'consumer_nam', 'date': 'date']"
I want to convert this to a dictionary type in Swift4.
Dictionaries in Swift can be represented by [String : Any], and many other ways.
let dictionary : [String : Any] = ["name" : "consumer_nam", "date" : "date"]
If what you're trying to do is parse the String, you can take a look here and here.
It looks like your String is supposed to be interpreted as a Dictionary. It looks a bit like a textual representation of JSON.
Find a spec for the exact format of that String, and then you write code to parse it.
It may be easier to convince whoever produced that string to produce for example a JSON document instead (which would be stored as Data, not String).

How do I convert Postgres dates to ISO8601 in JSON responses with Vapor 3 running on Heroku?

I have a Vapor 3 API up on Heroku. Unfortunately, it's not handling dates correctly. Originally, I thought I could just treat dates like strings for simplicity in Vapor, like so:
struct MyModel {
var time: String?
}
But whenever I fetch MyModels from the db and return it, the time key doesn't appear at all (while other keys and values have no problems). I thought I might be able to just change time's type to Date, but that resulted in the same thing, and I've already used ContentConfig to set the JsonEncoder.dateEncodingStrategy to .iso8601 (again, no luck – perhaps because dateEncodingStrategy only supports millis on Linux, which is what Heroku uses?).
How do I convert Postgres dates to ISO8601 in json with Vapor 3 running on Heroku?
Got it working! Just changed the properties to Dates, and manually converted request query parameters to Dates as well (for use in filter calls). So, a little more by hand than most things in Vapor 3, but not terrible.
Eg my model looks like this now:
struct MyModel {
var time: Date?
}
And then when I try to filter by date I do something like this:
var builder = MyModel.query(on: req)
if let afterString: String = try? self.query.get(String.self, at: "after") {
let afterDate: Date? = DateFormatter.iso8601Full.date(from: afterString)
builder = builder.filter(\.time > afterDate)
}
where after is a url parameter, and DateFormatter.iso8601Full is my iso8601 date formatter. Then when I'm returning an array of MyModels in a response, I map the array to an array of MyModelResponseObjects which look like this:
struct MyModelResponseObject {
var time: String?
}
by doing something like this:
myModelsFuture.all().map(to: [MyModelResponseObject].self, { (myModels) -> [MyModelResponseObject] in
return myModels.map { it in
return MyModelResponseObject(time: DateFormatter.iso8601Full.string(from: it.time ?? Date.init(timeIntervalSince1970: 0)))
}
}
So basically I'm manually converting the dates into the format that I want when returning them in JSON.

How to query a value stored as UInt64 from mongodb?

I am using mongokitten as interface between my osx app and mongodb.I store date as UInt64 into the db.In Db it is stored in this format - NumberLong("1514450415154").There is no issue when inserting and reading data from db since in both cases the value is simply 1514450415154.But when trying to query,just the value is not sufficient.Hence I'm not able to write the query.Can anyone help me find a possible solution?
I am using mongokitten major version:4, swift version:3,xcode 9.Yes I am using Codable to make use of the Encodable and Decodable protocols.
Sample code:
let dateUint : UInt64 = UInt64(date.timeIntervalSince1970 * 1000.0);
let query : Query = Query(aqt: .greaterThanOrEqual(key: "super.upd_dtm", val: dateUint as! Primitive))
Structure stored in db:
"_id" : "093FF386-1D53-4DFC-AC56-D2B778C7D6FE",
"super" : {
"rel_ver" : "",
"crt_in" : "macpro",
"crt_by" : "ABC",
"lst_syn" : NumberLong("1514875651306"),
"is_drty" : false,
"crt_dtm" : NumberLong("1514875651306"),
"upd_dtm" : NumberLong("1514875651306"),
"doc_ver" : NumberLong(0)
},
"prj_nme" : "project1",
"prj_id" : "4545C803-D41E-4A4F-9409-538FC183D8B3"
You'll need to provide a few more details regarding your requirements so I can properly answer your question.
Which MongoKitten version are you using?
Which Swift version are you using?
Are you using codable?
Can you post some code that reproduces the problem?
UInt64 isn't a standard MongoDB type, however Int64 and Int32 are. MongoKitten will try to convert an UInt64 to a numberlong (Int64) in the codable APIs. In the non-codable APIs you quite explicitly need to convert the UInt64 to a BSON supported primitive type, yourself
You can use a normal Int in your query. Since (almost) all devices/servers running Swift will be 64-bits, MongoKitten doesn't support 32-bits (although it might work). That means an Int is the same as Int64. If you store your dates inside MongoDb as a Date rather than an epoch integer you'll also be able to use Foundation.Date within MongoKitten, including for Queries.
let epoch = date.timeIntervalSince1970 * 1000.0)
let results = try collection.find("super.upd_dtm" >= epoch)

Can I create a Date object from a predefined string (typescript)?

I have a value returned in a string (numbers separated by commas) and I'd like to make a Date object out of it. It looks like this is not possible, can someone confirm and/or suggest me a solution.
This does not work :
let dateString='2017,3,22,0';
let dateFromString = new Date(dateString);
This works though (when I pass a list of numbers) :
let dateFromString = new Date(2017,3,22,0);
And this works also :
let dateString = '2008/05/10 12:08:20';
let dateFromString = new Date(dateString);
The goal would be to create a Date object from a uniform string. Is that possible ?
Can I create a Date object from a predefined string, which has only one type of separator (comma, colon, slash or whatever) ?
If your environment is compatible with ES6 (eg. Babel, TypeScript, modern Chrome/Firefox etc), you can use the string's .split(',') and decompose the array into arguments like the following:
const dateString = '2017,3,22,0';
const date = new Date(...dateString.split(',')); // date object for 2017/03/22
ES5 compatible version:
var dateString = '2017,1,2,0';
var date = new (Function.prototype.bind.apply(Date, [null].concat(dateString.split(','))));
As for how the .bind.apply method works with new, you can take a look at Use of .apply() with 'new' operator. Is this possible?
Note: Thanks to the two comments below for spotting my errors 👍