Kotlin parse `MMYYYY` into YearMonth - kotlin

I want to parse a MMYYYY field to YearMonth in kotlin.
Example tried :
import java.time.YearMonth
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeFormatterBuilder
val formatter: DateTimeFormatter = DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("MMYYYY")
.toFormatter(Locale.ENGLISH)
println(YearMonth.parse("011970", formatter))
it didn't work

Your pattern is incorrect, it uses the symbol for week based year (Y) instead of year (u) or maybe year of era (y).
Read more about the symbols in the JavaDocs of DateTimeFormatter, some of them relevant here are:
Symbol
Meaning
Presentation
Examples
G
era
text
AD; Anno Domini; A
u
year
year
2004; 04
y
year-of-era
year
2004; 04
…
…
…
…
M/L
month-of-year
number/text
7; 07; Jul; July; J
…
…
…
…
Y
week-based-year
year
1996; 96
I'd recommend you switch to year:
import java.util.Locale
import java.time.YearMonth
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeFormatterBuilder
val formatter: DateTimeFormatter = DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("MMuuuu")
.toFormatter(Locale.ENGLISH)
fun main() {
println(YearMonth.parse("011970", formatter))
}
This code prints 1970-01
Iif you are sure you will exclusively receive numerical Strings, you can also use a less complex DateTimeFormatter by leaving the check for case sensitivity:
val formatter = DateTimeFormatter.ofPattern("MMuuuu", Locale.ENGLISH)

Related

How to create a Kotlin Decimal Formatter

I would like to create a decimal formatter that would display up to 2 decimal digits, with a given separator.
For example with separator ","
input -> output
3.0 -> "3"
3.1 -> "3,1"
3.14 -> "3,14"
3.141 -> "3,14"
3.149 -> "3,15"
I would like to do this in Kotlin, I guess I must use DecimalFormat but don't understand how to do so. Could you please help me?
The code below was tested against all your examples and seemed to work well:
val locale = Locale("en", "UK")
val symbols = DecimalFormatSymbols(locale)
symbols.decimalSeparator = ','
val pattern = "#.##"
val decimalFormat = DecimalFormat(pattern, symbols)
val format = decimalFormat.format(3.14)
println(format) //3,14
To set a specific separator in your DecimalFormat, you can use setDecimalSeparator.
Pay attention to the pattern as # means:
A digit, leading zeroes are omitted
You can obviously change the locale to your fitting.
More information here.
You indeed might use java.text.NumberFormat to achieve your goal. The following should work is quite close to your example Swift code.
// you can change the separators by providing a Locale
val nf = java.text.NumberFormat
.getInstance(java.util.Locale.GERMAN)
nf.minimumFractionDigits = 0
nf.maximumFractionDigits = 2
// you may want to change the rounding mode
nf.roundingMode = java.math.RoundingMode.DOWN
println(nf.format(0)) // 0
println(nf.format(1)) // 1
println(nf.format(1.2)) // 1,2
println(nf.format(1.23)) // 1,23
println(nf.format(1.234)) // 1,23
println(nf.format(12.345)) // 12,34

In ANTLR how should I implement a Visitor with state / context?

I'm trying to write a simple ANTLR parser to handle date adjustment, so for example I could write: +1w+1d to mean "traverse a week and a day", or MIN(+30d, +1m) to mean "30 days from the input date, or 1 month, whichever is sooner". These rules should be composable, so MIN(+30d, +1m)+1d means "the day after (30 days from the input date, or 1 month from the input date, whichever is sooner)" and +1dMIN(+30d, +1m) means "30 days from (the day after the input date) or 1 month after (the day after the input date) whichever is sooner".
[I appreciate the examples here are relatively trite - the real grammar needs to understand about weekends, holidays, month boundaries etc, so it might be things like "one month after(the end of the input date's month or the Friday after the input date - whichever comes first)" etc etc]
The code I want to write is:
DateAdjutmeParser parser = buildFromString("MAX(+30d,+1m)");
ParseTree tree = parser.rootNode();
return new MyVisitor().visit(tree, LocalDate.of(2020,4,23)); //Not allowed extra parameters here.
The problem is how exactly can I pass the "context Date"? I can't store it in the MyVisitor class as a member since the visit() call is recursive and that would overwrite the context. I could build up a parallel set of objects that did have the right methods, but that seems a lot of boilerplate.
Is there an ANTLR solution?
More details:
This is the Visitor I'd like to write:
public class MyVisitor extends DateAdjustBaseVisitor<LocalDate> {
#Override
public LocalDate visitOffsetRule(DateAdjustParser.OffsetRuleContext ctx) {
LocalDate contextDate = ???; //
return contextDate.plus(Integer.valueOf(ctx.num.toString()), ChronoUnit.valueOf(ctx.unit.toString()));
}
#Override
public LocalDate visitMinMaxRule(DateAdjustParser.MinMaxRuleContext ctx) {
LocalDate contextDate = ???; //
LocalDate left = this.visitChildren(ctx.left, contextDate);
LocalDate right = this.visitChildren(ctx.right, contextDate);
if(ctx.type.getText().equals("MIN")) {
return left.compareTo(right) > 0 ? left : right;
} else {
return left.compareTo(right) < 0 ? left : right;
}
}
}
here's my grammar:
grammar DateAdjust;
rootNode: offset+;
offset
: num=NUMBER unit=UNIT #OffsetRule
| type=( MIN | MAX ) '(' left=offset ',' right=offset ')' #MinMaxRule
;
UNIT: [dwmy]; //Days Weeks Months Years
NUMBER: [+-]?[0..9]+;
MAX: 'MAX';
MIN: 'MIN';
Not an Antlr-specific solution, but a typical DSL solution is to use a scoped state table (aka symbol table) to accumulate the results of an AST/CST walk.
See this answer for an implementation. Another exists in the Antlr repository.

How can I get the value of a T-student distribution?

I have been reviewing the documentation of apache commons math and I find that it also calculates distributions, but I can not understand how it works.
I have two values
degrees of freedom = 13
confidence interval = 0.95
My problem is that it does not yield the value I need,
The objective is:
result = 1.771
import org.apache.commons.math3.distribution.TDistribution
fun calculo(a:Double, b:Double): Double {
val distf = TDistribution(a,b)
return distf.getNumericalMean()
}
fun main(args: Array<String>) {
val ko = calculo(13,0.95)
println(ko)
}
```
You can use the following:
new org.apache.commons.math3.distribution.TDistribution(deg_freedom).
inverseCumulativeProbability(probability)
Where deg_freedom=13, and probability=0.95.

Show or hide decimals

I have a double value, if that number is like this: 123.00 I need to show it as 123 only, without decimal places, but, if the number is like 123.23 or 123.2, I need to show it with the present decimal places: 123.23 or 123.2, as the case may be.
I have tried with decimal format but I couldn't find the right pattern.
It is a better way to do this than a string conversion and operate with substrings and things like that?
DecimalFormat is what you're looking for I think:
import java.text.DecimalFormat
fun main(args : Array<String>) {
val df = DecimalFormat("0.##")
println(df.format(123.0))
println(df.format(123.3))
println(df.format(123.32))
println(df.format(123.327))
}
Output:
123
123.3
123.32
123.33
Here's one way you could do it:
fun func(x: Double): String {
if (x.rem(1).compareTo(0) == 0){
return x.toInt().toString();
} else {
return x.toString();
}
}
print(func(1.32132)); //Returns 1.32132
print(func(3.00)); //Returns 3
You could use DecimalFormat with setMaximumFractionDigits. Creating an extension function would keep the complexity away from the call-site:
fun Double.toStringRounded(fracDigits: Int) = DecimalFormat().apply {
setMaximumFractionDigits(fracDigits)
}.format(this)
Usage:
3.14159.toStringRounded(2) // will be "3.14"

How to convert toFixed(2) in Kotlin

What should I write in the place of area.toFixed(2)
fun main(args: Array<String>) {
val a = 20
val h = 30
val area = a * h / 2
println("Triangle area = ${area.toFixed(2)}")
}
I think you really meet a problem that how to convert Javascript code to Kotlin code. You need to ask the question clearly at next time, :). you can use String#format instead, for example:
println("%.2f".format(1.0)) // print "1.00"
println("%.2f".format(1.253)) // print "1.25"
println("%.2f".format(1.255)) // print "1.26"
AND the area is an Int which means it will truncates the precision, Kotlin doesn't like as Javascript use the numeric by default, so you should let a*h divide by a Double, then your code is like as below:
// v--- use a `Double` instead
val area = a * h / 2.0
println("Triangle area = ${"%.2f".format(area)}")