I have an error when I try to subtract in Kotlin - kotlin

val year : Int = spinYear.getSelectedItem() as Int
selDate.text = "$year / $month / $date"
val curTime = LocalDateTime.now()
val curYear : Int = curTime.year
val difYear : Int = curYear - year
ageInMins.text = difYear.toString()
The language is Kotlin, and this is a part of my code.
The value year comes from a spinner named spinYear, and I got the selected value as an integer. Ultimately I want to substitute the text ageInMins with the value difYear.
I'm trying to define my difYear by subtracting the two variables: curYear and year, but the app crashes every time.
It seems like both of the variables I'm subtracting are of type Int, so I have no idea what to do with this problem.
If someone could give me an advice it would be great :)
I searched around Google to find information about this, but there was no useful information. I also tried to put .toInt() to the values but it didn't work. I tried every single thing I can think of, but it did not work. So I am seeking help from you guys.

Related

Kotlin: 'if' must have both main and 'else' branches if used as an expression

I am trying to run this code:
fun main() {
print("This is a calculator")
print("enter your first number")
val no1 = readLine()!!
print("enter your operation")
val operation1 = readLine()!!
print("enter your second number")
val no2 = readLine()!!
val result = if(operation1 == '*')
print("$val no1 * $val no2")
}
But I get the following error:
'if' must have both main and 'else' branches if used as an expression
Operator '==' cannot be applied to 'String' and 'Char' Keyword cannot
be used as a reference Keyword cannot be used as a reference
It also keeps coming up with Kotlin: Keyword cannot be used as a reference within my IDE.
I am very new to Kotlin and I am just trying to create a basic calculator, can you please help?
That code has three different compilation errors, and many other things to fix:
In the line:
print("$val no1 * $val no2")
the $val is a string template which would fill in the value of the variable val — but val isn't a variable; it's a keyword. (That's what's causing the ‘Keyword cannot be used as a reference’ error.) I think you want $no1 and $no2.
The test if(operation1 == '*') is comparing a string with a character. (Single-quotes give a character constant. A string contains characters, but it is not a character, so it can never be equal to a character.) The compiler tells you this with the error ‘Operator '==' cannot be applied to 'String' and 'Char'’. The simplest way to fix it is to provide a string by using double-quotes instead: "*".
The pair of lines:
val result = if(operation1 == '*')
print("$val no1 * $val no2")
is incomplete and doesn't make sense as it is. What do you want to do if operation1 isn't "*"? And what do you want to set result to in each case?
(It looks like you're trying to use if as an expression, and assign its result to result — but to use if as an expression you need to add an else branch too, so it knows what value to use in all cases. That's causing the compilation error ‘'if' must have both main and 'else' branches if used as an expression’.)
If this is the start of some code which will check for *, +, and other operators, then maybe you want to set the result and then print it, e.g.:
val result = if (operation1 == "*") /* … */
else if (operation2 == "+") /* … */
else /* … */
print(result)
(Though that would be simpler with when instead of if.)
If you fix the first issue by changing it to "$no1 * $no2", that will print e.g. 1 * 2. I'm guessing you want instead to calculate the product of two numbers. But no1 and no2 aren't numbers; they're strings. So you first have to convert them into numbers, e.g. with no1.toInt(). You also have to tell the compiler that you want to evaluate the * rather than just printing it. If you just want to print out the number, you could skip the string template entirely:
print(no1.toInt() * no2.toInt())
However, if you want to use a string template (e.g. if you want to add some text), you'd have to use the ${…} format to mark out the bit you want to evaluate:
print("${no1.toInt() * no2.toInt()}")
Some or all of the print(…) calls should probably be println(…). (println() adds a line-break after the string, while print() doesn't, leaving the next input or output to follow immediately on the same line.)
Even if all that's fixed, the code could fail in several ways if the user doesn't enter the expected input. (Both !! and toInt() can throw exceptions, e.g. if you press Enter without typing a number.) That's fine for an exercise, of course; but if this code ever got to production, you'd want to handle those possibilities better.
When you use $val, it is trying to access the val variable, but as $val is undefined, it can't, and freaks out because it doesn't know what to do.
Instead of print("$val no1 * $val no2"), you can use:
print("$no1 * $no2")
The code above will use the $no1 and $no2 variables that you want it to use.
In line 4 and 8, the input should be converted to Int, like this:
val no1 = readLine()!!.toInt()
val no2 = readLine()!!.toInt()
In the last line, val should not be written and should be as follows:
print("$no1 * $no2")
You can also add other operators using else if in the continuation of the if command

Struggling with simple boolean WHERE clause

Tired brain - perhaps you can help.
My table has two bit fields:
1) TestedByPCL and
2) TestedBySPC.
Both may = 1.
The user interface has two corresponding check boxes. In the code I convert the checks to int.
int TestedBySPC = SearchSPC ? 1 : 0;
int TestedByPCL = SearchPCL ? 1 : 0;
My WHERE clause looks something like this:
WHERE TestedByPCL = {TestedByPCL.ToString()} AND TestedBySPC = {TestedBySPC.ToString()}
The problem is when only one checkbox is selected I want to return rows having the corresponding field set to 1 or both fields set to 1.
Now when both fields are set to 1 my WHERE clause requires both check boxes to be checked instead of only one.
So, if one checkbox is ticked return records with with that field = 1 , regardless of whether the other field = 1.
Second attempt (I think I've got it now):
WHERE ((TestedByPCL = {chkTestedByPCL.IsChecked} AND TestedBySPC = {chkTestedBySPC.IsChecked})
OR
(TestedByPCL = 1 AND TestedBySPC = 1 AND 1 IN ({chkTestedByPCL.IsChecked}, {chkTestedBySPC.IsChecked})))
Misunderstood the question.
Change the AND to an OR:
WHERE TestedByPCL = {chkTestedByPCL.IsChecked} OR TestedBySPC = {chkTestedBySPC.IsChecked}
Also:
SQL Server does not have a Boolean data type, it's closest option is a bit data type.
The usage of curly brackets suggests using string concatenations to build your where clause. This might not be a big deal when you're handling checkboxes but it's a security risk when handling free text input as it's an open door for SQL injection attacks. Better use parameters whenever you can.

Filter result from database where row is null

I want to display all rows from database where row at specified column is empty (data is not inserted). To do that, in my onCreateLoader I wrote following code:
override fun onCreateLoader(p0: Int, p1: Bundle?): Loader<Cursor> {
val projection = arrayOf(
WalletEntry._ID,
WalletEntry.KEY_TITLE,
WalletEntry.KEY_MONEY,
WalletEntry.KEY_LAST_DATE,
WalletEntry.KEY_LAST_EXPENSE,
WalletEntry.KEY_LAST_TRANSACTION_TITLE,
WalletEntry.KEY_LOCALES,
WalletEntry.KEY_CURRENCY
)
val selection = "${WalletEntry.KEY_CURRENCY} = ?"
val selectionArgs = arrayOf("")
return applicationContext?.let { context ->
CursorLoader(context,
WalletEntry.CONTENT_URI,
projection,
selection,
selectionArgs,
null)
}!!
}
Where I want to display all results where WalletEntry.KEY_CURRENCY has no signed value, is empty. I tried to specify selectionArgs as null but it neither worked. So, how am I suppose to write selectionArgs to display all results where given row is empty?
To make my situation more clear I'll provide an app target. I'm learning kotlin and decided to write something like "bank" application where you can add different wallets and specify currencies. If you add a new currency it's being instantly added to the database to the column WalletEntry.KEY_CURRENCY. Then I have a list containing all "wallets", in which after adding a new currency an empty extra wallet appears. To avoid that I want to filter results and display only those, which do not have value passed in WalletEntry.CURRENCY column.
If you're looking for NULL values in that database column, I think you might be looking for:
val selection = "${WalletEntry.KEY_CURRENCY} IS NULL"
val selectionArgs = null
If the selectionArgs argument is not nullable, try setting it to emptyArray<String>()

Dates for different calendars

I am working on a project which is running in 2 countries already. Everything was fine until we deployed the project in Nepal. The problem is they are not working with standard Gregorian calendar. They have their own calendar called Bikram Sanwant Calendar. Our existing database has DateTime/Date columns which I cannot use any more because few months in their calendar have 32 days which is not a valid date according to the Gregorian calendar. So we have thought of saving all the dates in 3 different columns like Day,Month and year. Not just that but we also have used inbuilt standard SQL DateTime Functions like DateAdd, DateDiff etc... So I will also have to write my own functions and change all the queries, Stored Procedures and Functions.
Does anyone know how to deal with this or have better idea about this issue?
Please give your input and suggestions.
Thanks in advance.
Check this php code to convert AD to BS. Hope this will help you in understanding more.
<?php
//The Vikram Samvat calendar is 56 years 8 months and 14 days ahead (in count) of the solar Gregorian calendar
//date_default_timezone_set('Asia/Kathmandu');
$date = date('Y-m-d');
$ts1 = strtotime($date);
$year1 = date('Y', $ts1) + 56;
$month1 = date('m', $ts1) + 8;
$day1 = date('d', $ts1) + 14;
if($month1 >12) {
$year1 = $year1+1;
//$remMonth = $month1-12;
$month1 = $month1-12;
}
if($day1 >30) {
$month1 = $month1+1;
//$remMonth = $month1-12;
$day1 = $day1-30;
}
//$day1 = date('d', $ts1);
echo $year1."-".$month1."-".$day1;
?>

NHibernate Like with integer

I have a NHibernate search function where I receive integers and want to return results where at least the beginning coincides with the integers, e.g.
received integer: 729
returns: 729445, 7291 etc.
The database column is of type int, as is the property "Id" of Foo.
But
int id = 729;
var criteria = session.CreateCriteria(typeof(Foo))
criteria.Add(NHibernate.Criterion.Expression.InsensitiveLike("Id", id.ToString() + "%"));
return criteria.List<Foo>();
does result in an error (Could not convert parameter string to int32). Is there something wrong in the code, a work around, or other solution?
How about this:
int id = 729;
var criteria = session.CreateCriteria(typeof(Foo))
criteria.Add(Expression.Like(Projections.Cast(NHibernateUtil.String, Projections.Property("Id")), id.ToString(), MatchMode.Anywhere));
return criteria.List<Foo>();
Have you tried something like this:
int id = 729;
var criteria = session.CreateCriteria(typeof(Foo))
criteria.Add(NHibernate.Criterion.Expression.Like(Projections.SqlFunction("to_char", NHibernate.NHibernateUtil.String, Projections.Property("Id")), id.ToString() + "%"));
return criteria.List<Foo>();
The idea is convert the column before using a to_char function. Some databases do this automatically.
AFAIK, you'll need to store your integer as a string in the database if you want to use the built in NHibernate functionality for this (I would recommend this approach even without NHibernate - the minute you start doing 'like' searches you are dealing with a string, not a number - think US Zip Codes, etc...).
You could also do it mathematically in a database-specific function (or convert to a string as described in Thiago Azevedo's answer), but I imagine these options would be significantly slower, and also have potential to tie you to a specific database.