<commit_before>/*
 * Copyright (c) 2014 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package me.neilellis.dollar.types;

import me.neilellis.dollar.DollarStatic;
import me.neilellis.dollar.Type;
import me.neilellis.dollar.collections.ImmutableList;
import me.neilellis.dollar.var;
import org.jetbrains.annotations.NotNull;

import java.time.*;
import java.time.temporal.ChronoField;
import java.util.Arrays;
import java.util.Objects;

/**
 * @author <a href="http://uk.linkedin.com/in/neilellis"><NAME></a>
 */
public class DollarDate extends AbstractDollarSingleValue<Instant> {

    private static final double ONE_DAY_MILLIS = 24.0 * 60.0 * 60.0 * 1000.0;
    private static final double ONE_DAY_SECONDS = 24.0 * 60.0 * 60.0;

    public DollarDate(@NotNull ImmutableList<Throwable> errors, @NotNull Long value) {
        super(errors, Instant.ofEpochMilli(value));
    }

    public DollarDate(ImmutableList<Throwable> errors, Instant value) {
        super(errors, value);
    }

    public DollarDate(ImmutableList<Throwable> errors, LocalDateTime value) {
        super(errors, value.toInstant(ZoneOffset.UTC));
    }

    @NotNull
    @Override
    public var $abs() {
        return this;
    }

    @NotNull
    @Override
    public var $negate() {
        return DollarFactory.fromValue(-asDecimal(), errors());
    }

    @NotNull
    @Override
    public var $divide(@NotNull var v) {
        var rhsFix = v._fixDeep();
        if (rhsFix.isZero() || rhsFix.D() == null || rhsFix.D() == 0.0) {
            return DollarFactory.infinity(v.isPositive(), errors(), v.errors());
        }
        return DollarFactory.fromValue(asDecimal() / v.D(), errors(), v.errors());
    }

    @NotNull
    @Override
    public var $modulus(@NotNull var v) {
        return DollarFactory.fromValue(asDecimal() % v.D(), errors(), v.errors());
    }

    @NotNull
    @Override
    public var $multiply(@NotNull var v) {
        return DollarFactory.fromValue(asDecimal() * v.D(), errors(), v.errors());
    }

    @Override
    @NotNull
    public Integer I() {
        return asDecimal().intValue();
    }

    @NotNull
    @Override
    public Number N() {
        return asDecimal();
    }

    @Override public int sign() {
        return (int) Math.signum(asDecimal());
    }

    private Double asDecimal() {
        try {
            final long millis = value.toEpochMilli();
            return ((double) millis) / (24 * 60 * 60 * 1000);
        } catch (ArithmeticException e) {
            final long seconds = value.getEpochSecond();
            return ((double) seconds) / (24 * 60 * 60);

        }
    }

    @Override
    public var $as(Type type) {
        if (type.equals(Type.BOOLEAN)) {
            return DollarStatic.$(true);
        } else if (type.equals(Type.STRING)) {
            return DollarStatic.$(value.toString());
        } else if (type.equals(Type.LIST)) {
            return DollarStatic.$(Arrays.asList(this));
        } else if (type.equals(Type.MAP)) {
            return DollarStatic.$("value", this);
        } else if (type.equals(Type.DECIMAL)) {
            return DollarStatic.$(asDecimal());
        } else if (type.equals(Type.INTEGER)) {
            return DollarStatic.$(asDecimal().longValue());
        } else if (type.equals(Type.VOID)) {
            return DollarStatic.$void();
        } else {
            return DollarFactory.failure(me.neilellis.dollar.types.ErrorType.INVALID_CAST);
        }
    }

    @Override public Type $type() {
        return Type.DATE;
    }

    @Override
    public boolean is(@NotNull Type... types) {
        for (Type type : types) {
            if (type == Type.DATE) {
                return true;
            }
        }
        return false;
    }

    @NotNull @Override public var $get(@NotNull var key) {
        return DollarFactory.fromValue(LocalDateTime.ofInstant(value, ZoneId.systemDefault()).get(
                                               ChronoField.valueOf(key.S().toUpperCase())),
                                       errors());
    }

//    @NotNull
//    @Override
//    public var $dec(@NotNull var amount) {
//        return DollarFactory.fromValue(value.plusSeconds((long) (ONE_DAY_SECONDS * amount.D())), errors(),
//                                       amount.errors());
//    }
//
//    @NotNull
//    @Override
//    public var $inc(@NotNull var amount) {
//        return DollarFactory.fromValue(value.minusSeconds((long) (ONE_DAY_SECONDS * amount.D())), errors(),
//                                       amount.errors());
//    }

    @NotNull @Override public var $set(@NotNull var key, Object v) {
        return DollarFactory.fromValue(
                value.with(ChronoField.valueOf(key.S().toUpperCase()), DollarFactory.fromValue(v).L()), errors(),
                key.errors());
    }

    @NotNull
    @Override
    public var $plus(var rhs) {
        var rhsFix = rhs._fixDeep();
        if (rhsFix.isString()) {
            return DollarFactory.fromValue(toString() + rhsFix.toString(), errors(), rhsFix.errors());
        } else if (rhsFix.isInfinite()) {
            return rhs;
        } else if (rhsFix.isList()) {
            return DollarFactory.fromValue(rhsFix.$prepend(this), errors(), rhsFix.errors());
        } else if (rhsFix.isRange()) {
            return DollarFactory.fromValue(rhsFix.$plus(this), errors(), rhsFix.errors());
        } else {
            try {
                return DollarFactory.fromValue(value.plusSeconds((long) (ONE_DAY_SECONDS * rhsFix.D())), errors(),
                                               rhsFix.errors());<commit_msg>Better predictive type system.<commit_after>/*
 * Copyright (c) 2014 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package me.neilellis.dollar.types;

import me.neilellis.dollar.DollarStatic;
import me.neilellis.dollar.Type;
import me.neilellis.dollar.collections.ImmutableList;
import me.neilellis.dollar.var;
import org.jetbrains.annotations.NotNull;

import java.time.*;
import java.time.temporal.ChronoField;
import java.util.Arrays;
import java.util.Objects;

/**
 * @author <a href="http://uk.linkedin.com/in/neilellis"><NAME></a>
 */
public class DollarDate extends AbstractDollarSingleValue<Instant> {

    private static final double ONE_DAY_MILLIS = 24.0 * 60.0 * 60.0 * 1000.0;
    private static final double ONE_DAY_SECONDS = 24.0 * 60.0 * 60.0;

    public DollarDate(@NotNull ImmutableList<Throwable> errors, @NotNull Long value) {
        super(errors, Instant.ofEpochMilli(value));
    }

    public DollarDate(ImmutableList<Throwable> errors, Instant value) {
        super(errors, value);
    }

    public DollarDate(ImmutableList<Throwable> errors, LocalDateTime value) {
        super(errors, value.toInstant(ZoneOffset.UTC));
    }

    @NotNull
    @Override
    public var $abs() {
        return this;
    }

    @NotNull
    @Override
    public var $negate() {
        return DollarFactory.fromValue(-asDecimal(), errors());
    }

    @NotNull
    @Override
    public var $divide(@NotNull var v) {
        var rhsFix = v._fixDeep();
        if (rhsFix.isZero() || rhsFix.D() == null || rhsFix.D() == 0.0) {
            return DollarFactory.infinity(v.isPositive(), errors(), v.errors());
        }
        return DollarFactory.fromValue(asDecimal() / v.D(), errors(), v.errors());
    }

    @NotNull
    @Override
    public var $modulus(@NotNull var v) {
        return DollarFactory.fromValue(asDecimal() % v.D(), errors(), v.errors());
    }

    @NotNull
    @Override
    public var $multiply(@NotNull var v) {
        return DollarFactory.fromValue(asDecimal() * v.D(), errors(), v.errors());
    }

    @Override
    @NotNull
    public Integer I() {
        return asDecimal().intValue();
    }

    @NotNull
    @Override
    public Number N() {
        return asDecimal();
    }

    @Override public int sign() {
        return (int) Math.signum(asDecimal());
    }

    private Double asDecimal() {
        try {
            final long millis = value.toEpochMilli();
            return ((double) millis) / (24 * 60 * 60 * 1000);
        } catch (ArithmeticException e) {
            final long seconds = value.getEpochSecond();
            return ((double) seconds) / (24 * 60 * 60);

        }
    }

    @Override
    public var $as(Type type) {
        if (type.equals(Type.BOOLEAN)) {
            return DollarStatic.$(true);
        } else if (type.equals(Type.STRING)) {
            return DollarStatic.$(value.toString());
        } else if (type.equals(Type.LIST)) {
            return DollarStatic.$(Arrays.asList(this));
        } else if (type.equals(Type.MAP)) {
            return DollarStatic.$("value", this);
        } else if (type.equals(Type.DECIMAL)) {
            return DollarStatic.$(asDecimal());
        } else if (type.equals(Type.INTEGER)) {
            return DollarStatic.$(asDecimal().longValue());
        } else if (type.equals(Type.VOID)) {
            return DollarStatic.$void();
        } else {
            return DollarFactory.failure(me.neilellis.dollar.types.ErrorType.INVALID_CAST);
        }
    }

    @Override public Type $type() {
        return Type.DATE;
    }

    @Override
    public boolean is(@NotNull Type... types) {
        for (Type type : types) {
            if (type == Type.DATE) {
                return true;
            }
        }
        return false;
    }

    @NotNull @Override public var $get(@NotNull var key) {
        final LocalDateTime localDateTime = LocalDateTime.ofInstant(value, ZoneId.systemDefault());
        return DollarFactory.fromValue(localDateTime.get(ChronoField.valueOf(key.S().toUpperCase())), errors());
    }

//    @NotNull
//    @Override
//    public var $dec(@NotNull var amount) {
//        return DollarFactory.fromValue(value.plusSeconds((long) (ONE_DAY_SECONDS * amount.D())), errors(),
//                                       amount.errors());
//    }
//
//    @NotNull
//    @Override
//    public var $inc(@NotNull var amount) {
//        return DollarFactory.fromValue(value.minusSeconds((long) (ONE_DAY_SECONDS * amount.D())), errors(),
//                                       amount.errors());
//    }

    @NotNull @Override public var $set(@NotNull var key, Object v) {
        return DollarFactory.fromValue(
                LocalDateTime.ofInstant(value, ZoneId.systemDefault()).with(ChronoField.valueOf(key.S().toUpperCase()),
                                                                            DollarFactory.fromValue(v).L()),
                errors(),
                key.errors());
    }

    @NotNull
    @Override
    public var $plus(var rhs) {
        var rhsFix = rhs._fixDeep();
        if (rhsFix.isString()) {
            return DollarFactory.fromValue(toString() + rhsFix.toString(), errors(), rhsFix.errors());
        } else if (rhsFix.isInfinite()) {
            return rhs;
        } else if (rhsFix.isList()) {
            return DollarFactory.fromValue(rhsFix.$prepend(this), errors(), rhsFix.errors());
        } else if (rhsFix.isRange()) {
            return DollarFactory.fromValue(rhsFix.$plus(this), errors(), rhsFix.errors());
        } else {
            try {
                return DollarFactory.fromValue(value.plusSeconds((long) (ONE_DAY_SECONDS * rhsFix.D())), errors(),
                                               rhsFix.errors());
{'fraction_non_alphanumeric': 0.1320846116583239, 'fraction_numerical': 0.007912158889068302, 'mean_word_length': 2.2839342523860022, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4940405', 'n_tokens_mistral': 3662, 'n_tokens_neox': 3473, 'n_words': 858}