Returns whether input date is the first day of Lunar year or not. - Android java.util

Android examples for java.util:Day

Description

Returns whether input date is the first day of Lunar year or not.

Demo Code

/*/*from  ww  w .j  ava 2s.c om*/
 * Copyright (C) 2011  Nguyen Hoang Ton, a.k.a Ton Nguyen - tonng86@gmail.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
import java.util.Calendar;
import android.util.Log;

public class Main{
    private static final String TAG = "LunarCalendarUtil";
    private static final boolean DEBUG = false;
    private static final double PI = Math.PI;
    private static final double LOCAL_TIMEZONE = 7.0;
    /**
     * Returns whether input date is the first day of Lunar year or not.
     * @param today Input date to check.
     * @return <code>true</code> if input date was the first day of Lunar year, otherwise <code>false</code>.
     */
    public static boolean isFirstDayOfLunarYear(Calendar today) {
        if (DEBUG)
            Log.d(TAG,
                    "checking if " + today.get(Calendar.DAY_OF_MONTH) + "/"
                            + today.get(Calendar.MONTH) + 1 + "/"
                            + today.get(Calendar.YEAR)
                            + " is FirstDayOfLunarYear");
        int[] value = LunarCalendarUtil.Solar2Lunar(
                today.get(Calendar.DAY_OF_MONTH),
                today.get(Calendar.MONTH) + 1, today.get(Calendar.YEAR));
        if (DEBUG)
            Log.d(TAG, "Lunar date: " + value[0] + "/" + value[1] + "/"
                    + value[2]);
        return (value != null && value[0] == 1 && value[1] == 1);
    }
    /**
     * Convert Solar date to Lunar date.
     * @param D The value used to set the DAY_OF_MONTH calendar field.
     * @param M The value used to set the MONTH calendar field. Month value is 1-based. e.g., 1 for January.
     * @param Y The value used to set the YEAR calendar field.
     * @return An array of integer: [dd],[mm],[yy],[leap] (leap year = 1)
     */
    public static int[] Solar2Lunar(int D, int M, int Y) {
        int yy = Y;
        int[][] ly = LunarYear(Y); // Please cache the result of this computation for later use!!!
        int[] month11 = ly[ly.length - 1];
        double jdToday = LocalToJD(D, M, Y);
        double jdMonth11 = LocalToJD(month11[0], month11[1], month11[2]);
        if (jdToday >= jdMonth11) {
            ly = LunarYear(Y + 1);
            yy = Y + 1;
        }
        int i = ly.length - 1;
        while (jdToday < LocalToJD(ly[i][0], ly[i][1], ly[i][2])) {
            i--;
        }
        int dd = (int) (jdToday - LocalToJD(ly[i][0], ly[i][1], ly[i][2])) + 1;
        int mm = ly[i][3];
        if (mm >= 11) {
            yy--;
        }
        return new int[] { dd, mm, yy, ly[i][4] };
    }
    private static int[][] LunarYear(int Y) {
        int[][] ret = null;
        int[] month11A = LunarMonth11(Y - 1);
        double jdMonth11A = LocalToJD(month11A[0], month11A[1], month11A[2]);
        int k = (int) Math
                .floor(0.5 + (jdMonth11A - 2415021.076998695) / 29.530588853);
        int[] month11B = LunarMonth11(Y);
        double off = LocalToJD(month11B[0], month11B[1], month11B[2])
                - jdMonth11A;
        boolean leap = off > 365.0;
        if (!leap) {
            ret = new int[13][5];
        } else {
            ret = new int[14][5];
        }
        ret[0] = new int[] { month11A[0], month11A[1], month11A[2], 0, 0 };
        ret[ret.length - 1] = new int[] { month11B[0], month11B[1],
                month11B[2], 0, 0 };
        for (int i = 1; i < ret.length - 1; i++) {
            double nm = NewMoon(k + i);
            int[] a = LocalFromJD(nm);
            ret[i] = new int[] { a[0], a[1], a[2], 0, 0 };
        }
        for (int i = 0; i < ret.length; i++) {
            ret[i][3] = MOD(i + 11, 12);
        }
        if (leap) {
            initLeapYear(ret);
        }
        return ret;
    }
    private static double LocalToJD(int D, int M, int Y) {
        return UniversalToJD(D, M, Y) - LOCAL_TIMEZONE / 24.0;
    }
    private static int[] LunarMonth11(int Y) {
        double off = LocalToJD(31, 12, Y) - 2415021.076998695;
        int k = INT(off / 29.530588853);
        double jd = NewMoon(k);
        int[] ret = LocalFromJD(jd);
        double sunLong = SunLongitude(LocalToJD(ret[0], ret[1], ret[2])); // sun longitude at local midnight
        if (sunLong > 3 * PI / 2) {
            jd = NewMoon(k - 1);
        }
        return LocalFromJD(jd);
    }
    private static double NewMoon(int k) {
        double T = k / 1236.85; // Time in Julian centuries from 1900 January 0.5
        double T2 = T * T;
        double T3 = T2 * T;
        double dr = PI / 180;
        double Jd1 = 2415020.75933 + 29.53058868 * k + 0.0001178 * T2
                - 0.000000155 * T3;
        Jd1 = Jd1 + 0.00033
                * Math.sin((166.56 + 132.87 * T - 0.009173 * T2) * dr); // Mean new moon
        double M = 359.2242 + 29.10535608 * k - 0.0000333 * T2 - 0.00000347
                * T3; // Sun's mean anomaly
        double Mpr = 306.0253 + 385.81691806 * k + 0.0107306 * T2
                + 0.00001236 * T3; // Moon's mean anomaly
        double F = 21.2964 + 390.67050646 * k - 0.0016528 * T2 - 0.00000239
                * T3; // Moon's argument of latitude
        double C1 = (0.1734 - 0.000393 * T) * Math.sin(M * dr) + 0.0021
                * Math.sin(2 * dr * M);
        C1 = C1 - 0.4068 * Math.sin(Mpr * dr) + 0.0161
                * Math.sin(dr * 2 * Mpr);
        C1 = C1 - 0.0004 * Math.sin(dr * 3 * Mpr);
        C1 = C1 + 0.0104 * Math.sin(dr * 2 * F) - 0.0051
                * Math.sin(dr * (M + Mpr));
        C1 = C1 - 0.0074 * Math.sin(dr * (M - Mpr)) + 0.0004
                * Math.sin(dr * (2 * F + M));
        C1 = C1 - 0.0004 * Math.sin(dr * (2 * F - M)) - 0.0006
                * Math.sin(dr * (2 * F + Mpr));
        C1 = C1 + 0.0010 * Math.sin(dr * (2 * F - Mpr)) + 0.0005
                * Math.sin(dr * (2 * Mpr + M));
        double deltat;
        if (T < -11) {
            deltat = 0.001 + 0.000839 * T + 0.0002261 * T2 - 0.00000845
                    * T3 - 0.000000081 * T * T3;
        } else {
            deltat = -0.000278 + 0.000265 * T + 0.000262 * T2;
        }
        ;
        double JdNew = Jd1 + C1 - deltat;
        return JdNew;
    }
    private static int[] LocalFromJD(double JD) {
        return UniversalFromJD(JD + LOCAL_TIMEZONE / 24.0);
    }
    private static int MOD(int x, int y) {
        int z = x - (int) (y * Math.floor(((double) x / y)));
        if (z == 0) {
            z = y;
        }
        return z;
    }
    private static void initLeapYear(int[][] ret) {
        double[] sunLongitudes = new double[ret.length];
        for (int i = 0; i < ret.length; i++) {
            int[] a = ret[i];
            double jdAtMonthBegin = LocalToJD(a[0], a[1], a[2]);
            sunLongitudes[i] = SunLongitude(jdAtMonthBegin);
        }
        boolean found = false;
        for (int i = 0; i < ret.length; i++) {
            if (found) {
                ret[i][3] = MOD(i + 10, 12);
                continue;
            }
            double sl1 = sunLongitudes[i];
            double sl2 = sunLongitudes[i + 1];
            boolean hasMajorTerm = Math.floor(sl1 / PI * 6) != Math
                    .floor(sl2 / PI * 6);
            if (!hasMajorTerm) {
                found = true;
                ret[i][4] = 1;
                ret[i][3] = MOD(i + 10, 12);
            }
        }
    }
    private static double UniversalToJD(int D, int M, int Y) {
        double JD;
        if (Y > 1582 || (Y == 1582 && M > 10)
                || (Y == 1582 && M == 10 && D > 14)) {
            JD = 367 * Y - INT(7 * (Y + INT((M + 9) / 12)) / 4)
                    - INT(3 * (INT((Y + (M - 9) / 7) / 100) + 1) / 4)
                    + INT(275 * M / 9) + D + 1721028.5;
        } else {
            JD = 367 * Y - INT(7 * (Y + 5001 + INT((M - 9) / 7)) / 4)
                    + INT(275 * M / 9) + D + 1729776.5;
        }
        return JD;
    }
}

Related Tutorials