How to validate an input string as a valid date in Kotlin? - date

So my Kotlin app is accepting an input String that should be a date in a certain format:
fun haveFun(dateStr: String){
var formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy")
var formattedDate = dateStr.format(formatter)
println(formattedDate)
}
The issue is that no matter which input string I send, it seems that everything is valid and no error is thrown.
The program is cool with whatever text I sent it: 61-Boby-2019 or even I'm not a date
From Java I'm used to some exception to be thrown or an isValid method, but I didn't find such yet in Kotlin

This should work. instead of using the format() use parse() it will throw exception if it fails and handle that at calling side.
#Throws(ParseException::class)
fun haveFun(dateStr: String) {
var formatter = SimpleDateFormat("dd-MMM-yyyy", Locale.getDefault())
val date = formatter.parse(dateStr)
println(date)
}
it will throw error like below:
java.text.ParseException: Unparseable date: "im not date"

You are using the wrong methods to format your date.
The method format which you are using (dateStr.format(formatter)) is for formatting the input which takes the current string as a format string as stated here:
fun String.format(vararg args: Any?): String Uses this string as a
format string and returns a string obtained by substituting the
specified arguments, using the default locale.
You need to do something else in order to achieve what you are looking for.
var formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy")
formatter.format(LocalDate.now()) //12-Dec-2019

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.

Kotlin equivalent of %# in swift

i am new to kotlin.
In swift i can do :
let endpoint = "categories/" + "%#/issues/"
let number = "4"
let finalstring = String(format: endpoint, number)
The final output of the string will be : categories/4/issues/ as a string .
I have looked at string format in kotlin but it's only work afterwards meaning that i can't define a template for my string and fill it later.
var value1 = "categories/"
var value2 = 4
var value3 = "/issues/"
println(java.lang.String.format("%s%d%s", value1, value2, value3))
This give me the same result but it's mean that i have to manualy write the end of the string.
What i want to do i to have a template for my string in a Road file.
Then complet my string at the run time. The probleme is that the part of my string that i want to complete is in the middle of the string.
Of course i can use substring and remplace but i am looking for a clean way to do it as in swift.
Thanks for helping.
One possible option would be to define a local function that does the formatting:
fun requestString(number: Int) = "categories/$number/issues/"
val finalString = requestString(4)
You can create your format string up front with all the constant parts, and with relevant placeholders (like %d for numbers) (more info in the javadoc).
Later, use the regular Java String.format() later with the parameters:
// define this constant up front
val format = "categories/%d/issues/"
// and then later:
val categoryId = 4
println(String.format(format, categoryId))
You already have the answer right there in your example, you just have to put it together.
String.format takes %s as placeholder for a String or %d for a number (and many more placeholder options).
So your template string would be: "categories/%d/issues/". To format it you use:
val format = "categories/%d/issues/"
val number = 4
val string = String.format(format, number)
About interpolation vs formatting, they can be used in different situations.
If you have the template string available in source code then you would use interpolation:
val string = "categories/${category.id}/issues/"
But when you have no control over the string, because it comes from an external source (such as a file), then you would have to use the formatting.

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 👍

NSNull into a Struct with a property of type NSDate

I have an object from the server that is recognized by Swift 2.1 as either NSDate or NSNull. I want to put it into a struct with a property of type NSDate.
Is that possible? If not, how should I handle this to be type safe later when I use it?
struct Data {
var completedAt: [NSDate]
var name: [String]
var gender: [Bool]
}
but sometimes completedAt comes from the server as NSNull:
completedAt = "<null>";
Any help is very much appreciated, thank you.
Based on my interpretation of the text in the question you didn't mean to declare the variables as arrays.
This is how I handle my parson and I think it works pretty neatly.
The date formatter should probable not be initiated in every iteration of the constructor. If you won't use the date regularly you might want to keep the detesting until you need to parse the date or you can have a static date formatter utility that you only instantiate once.
struct Data {
var completedAt: NSDate?
var name: String
var gender: Bool
init?(dictionary: [String:AnyObject]) {
//Guessing that you want some of the values non optional...
guard let name = dictionary["name"] as? String,
let gender = dictionary["gender"] as? String
else {
return nil
}
self.name = name
self.gender = gender
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
//safe handle of optional values
if let completedAtString = dictionary["completedAt"] as? String, completedAt = dateFormater.dateFromString(completedAtString) {
self.completedAt = completedAt
}
}
}
Take a step back. For each item that the server might provide, there is no guarantee whatsoever that you receive what you expect, since you cannot control the server. So you need to decide how to react to which input.
In the case of expecting a date for example (if your data comes in JSON, that means you likely expect a string formatted in a certain way), the actual data that you receive might be an array, dictionary, string, number, bool, null, or nothing. You might then for example decide that you want to interpret nothing or null or an empty string as nil, that you want to interpret a string containing a well-formatted date as an NSDate, and anything else a fatal error in a debug version, and as either nothing or a fatal error in a release version. On the other hand, if an NSDate is absolutely required then you might interpret anything that doesn't give an NSDate as an error.
Then you write a function that delivers exactly what you want and use it. That way you can parse complex data, with your code warning you when something isn't as it should be, and with your code either surviving any possible input, or deliberately crashing on wrong input, as you want it.

Getting the current time as a decimal point number

I want to be able to get the current time as a decimal point number so it can be used. so for example if the time is 13:46 I want to get it as 13.46
It seems simple but I am struggling getting to it.
We can use an NSDateFormatter to do exactly this:
extension NSDate {
func currentTime() -> String {
let formatter = NSDateFormatter()
formatter.dateFormat = "HH.mm"
return formatter.stringFromDate(self)
}
}
And now we just use it by calling it on any instance of NSDate:
let now = NSDate()
print(now.currentTime())
you can stringify the time and serch lastindexOf(":") and substitue it with a "."
UPDATE
I don't really catch what program language are you using, but it's plenty of library for stringify object so if you have a 13:46 you can convert it to String and, in the same string library you could find the method lastIndexOf(char). But if you don't find it you can always write following this concepts:
String are an array of Char so you can cycle it and convert the char in that position in the char you need.