Tasker thông báo các sự kiện Âm Dương Lịch

Tôi dùng Tasker trên Android để kiểm tra các sự kiện theo ngày Âm Lịch (và cả Dương lịch) và thực hiện một hoạt động (Action) tương ứng.

Tính toán lịch âm dương và xử lý sự kiện

Tính toán Âm Lịch là một công việc phức tạp, không thể sử dụng các Action mặc định của Tasker được.

Để tính toán và xử lý sự kiện trên Tasker, tôi sẽ tạo một JavaScript Action trên cơ sở là mã nguồn Lunisolar Calendar của anh Hồ Ngọc Đức tại đây.

Việc của tôi chỉ là bổ sung chút tính toán và lưu trữ thông tin về ngày diễn ra sự kiện vào biến local %event (kiểu array) của Tasker trong đoạn cuối của script này.

/sdcard/Documents/amlich.js

/**
 * Copyright 2004 Ho Ngoc Duc [http://come.to/duc]. All Rights Reserved.
 */
var TK19 = new Array(
    0x30baa3, 0x56ab50, 0x422ba0, 0x2cab61, 0x52a370, 0x3c51e8, 0x60d160, 0x4ae4b0, 0x376926, 0x58daa0,
    0x445b50, 0x3116d2, 0x562ae0, 0x3ea2e0, 0x28e2d2, 0x4ec950, 0x38d556, 0x5cb520, 0x46b690, 0x325da4,
    0x5855d0, 0x4225d0, 0x2ca5b3, 0x52a2b0, 0x3da8b7, 0x60a950, 0x4ab4a0, 0x35b2a5, 0x5aad50, 0x4455b0,
    0x302b74, 0x562570, 0x4052f9, 0x6452b0, 0x4e6950, 0x386d56, 0x5e5aa0, 0x46ab50, 0x3256d4, 0x584ae0,
    0x42a570, 0x2d4553, 0x50d2a0, 0x3be8a7, 0x60d550, 0x4a5aa0, 0x34ada5, 0x5a95d0, 0x464ae0, 0x2eaab4,
    0x54a4d0, 0x3ed2b8, 0x64b290, 0x4cb550, 0x385757, 0x5e2da0, 0x4895d0, 0x324d75, 0x5849b0, 0x42a4b0,
    0x2da4b3, 0x506a90, 0x3aad98, 0x606b50, 0x4c2b60, 0x359365, 0x5a9370, 0x464970, 0x306964, 0x52e4a0,
    0x3cea6a, 0x62da90, 0x4e5ad0, 0x392ad6, 0x5e2ae0, 0x4892e0, 0x32cad5, 0x56c950, 0x40d4a0, 0x2bd4a3,
    0x50b690, 0x3a57a7, 0x6055b0, 0x4c25d0, 0x3695b5, 0x5a92b0, 0x44a950, 0x2ed954, 0x54b4a0, 0x3cb550,
    0x286b52, 0x4e55b0, 0x3a2776, 0x5e2570, 0x4852b0, 0x32aaa5, 0x56e950, 0x406aa0, 0x2abaa3, 0x50ab50
); /* Years 2000-2099 */

var TK20 = new Array(
    0x3c4bd8, 0x624ae0, 0x4ca570, 0x3854d5, 0x5cd260, 0x44d950, 0x315554, 0x5656a0, 0x409ad0, 0x2a55d2,
    0x504ae0, 0x3aa5b6, 0x60a4d0, 0x48d250, 0x33d255, 0x58b540, 0x42d6a0, 0x2cada2, 0x5295b0, 0x3f4977,
    0x644970, 0x4ca4b0, 0x36b4b5, 0x5c6a50, 0x466d50, 0x312b54, 0x562b60, 0x409570, 0x2c52f2, 0x504970,
    0x3a6566, 0x5ed4a0, 0x48ea50, 0x336a95, 0x585ad0, 0x442b60, 0x2f86e3, 0x5292e0, 0x3dc8d7, 0x62c950,
    0x4cd4a0, 0x35d8a6, 0x5ab550, 0x4656a0, 0x31a5b4, 0x5625d0, 0x4092d0, 0x2ad2b2, 0x50a950, 0x38b557,
    0x5e6ca0, 0x48b550, 0x355355, 0x584da0, 0x42a5b0, 0x2f4573, 0x5452b0, 0x3ca9a8, 0x60e950, 0x4c6aa0,
    0x36aea6, 0x5aab50, 0x464b60, 0x30aae4, 0x56a570, 0x405260, 0x28f263, 0x4ed940, 0x38db47, 0x5cd6a0,
    0x4896d0, 0x344dd5, 0x5a4ad0, 0x42a4d0, 0x2cd4b4, 0x52b250, 0x3cd558, 0x60b540, 0x4ab5a0, 0x3755a6,
    0x5c95b0, 0x4649b0, 0x30a974, 0x56a4b0, 0x40aa50, 0x29aa52, 0x4e6d20, 0x39ad47, 0x5eab60, 0x489370,
    0x344af5, 0x5a4970, 0x4464b0, 0x2c74a3, 0x50ea50, 0x3d6a58, 0x6256a0, 0x4aaad0, 0x3696d5, 0x5c92e0
); /* Years 1900-1999 */

var TK21 = new Array(
    0x46c960, 0x2ed954, 0x54d4a0, 0x3eda50, 0x2a7552, 0x4e56a0, 0x38a7a7, 0x5ea5d0, 0x4a92b0, 0x32aab5,
    0x58a950, 0x42b4a0, 0x2cbaa4, 0x50ad50, 0x3c55d9, 0x624ba0, 0x4ca5b0, 0x375176, 0x5c5270, 0x466930,
    0x307934, 0x546aa0, 0x3ead50, 0x2a5b52, 0x504b60, 0x38a6e6, 0x5ea4e0, 0x48d260, 0x32ea65, 0x56d520,
    0x40daa0, 0x2d56a3, 0x5256d0, 0x3c4afb, 0x6249d0, 0x4ca4d0, 0x37d0b6, 0x5ab250, 0x44b520, 0x2edd25,
    0x54b5a0, 0x3e55d0, 0x2a55b2, 0x5049b0, 0x3aa577, 0x5ea4b0, 0x48aa50, 0x33b255, 0x586d20, 0x40ad60,
    0x2d4b63, 0x525370, 0x3e49e8, 0x60c970, 0x4c54b0, 0x3768a6, 0x5ada50, 0x445aa0, 0x2fa6a4, 0x54aad0,
    0x4052e0, 0x28d2e3, 0x4ec950, 0x38d557, 0x5ed4a0, 0x46d950, 0x325d55, 0x5856a0, 0x42a6d0, 0x2c55d4,
    0x5252b0, 0x3ca9b8, 0x62a930, 0x4ab490, 0x34b6a6, 0x5aad50, 0x4655a0, 0x2eab64, 0x54a570, 0x4052b0,
    0x2ab173, 0x4e6930, 0x386b37, 0x5e6aa0, 0x48ad50, 0x332ad5, 0x582b60, 0x42a570, 0x2e52e4, 0x50d160,
    0x3ae958, 0x60d520, 0x4ada90, 0x355aa6, 0x5a56d0, 0x462ae0, 0x30a9d4, 0x54a2d0, 0x3ed150, 0x28e952
); /* Years 2000-2099 */

var TK22 = new Array(
    0x4eb520, 0x38d727, 0x5eada0, 0x4a55b0, 0x362db5, 0x5a45b0, 0x44a2b0, 0x2eb2b4, 0x54a950, 0x3cb559,
    0x626b20, 0x4cad50, 0x385766, 0x5c5370, 0x484570, 0x326574, 0x5852b0, 0x406950, 0x2a7953, 0x505aa0,
    0x3baaa7, 0x5ea6d0, 0x4a4ae0, 0x35a2e5, 0x5aa550, 0x42d2a0, 0x2de2a4, 0x52d550, 0x3e5abb, 0x6256a0,
    0x4c96d0, 0x3949b6, 0x5e4ab0, 0x46a8d0, 0x30d4b5, 0x56b290, 0x40b550, 0x2a6d52, 0x504da0, 0x3b9567,
    0x609570, 0x4a49b0, 0x34a975, 0x5a64b0, 0x446a90, 0x2cba94, 0x526b50, 0x3e2b60, 0x28ab61, 0x4c9570,
    0x384ae6, 0x5cd160, 0x46e4a0, 0x2eed25, 0x54da90, 0x405b50, 0x2c36d3, 0x502ae0, 0x3a93d7, 0x6092d0,
    0x4ac950, 0x32d556, 0x58b4a0, 0x42b690, 0x2e5d94, 0x5255b0, 0x3e25fa, 0x6425b0, 0x4e92b0, 0x36aab6,
    0x5c6950, 0x4674a0, 0x31b2a5, 0x54ad50, 0x4055a0, 0x2aab73, 0x522570, 0x3a5377, 0x6052b0, 0x4a6950,
    0x346d56, 0x585aa0, 0x42ab50, 0x2e56d4, 0x544ae0, 0x3ca570, 0x2864d2, 0x4cd260, 0x36eaa6, 0x5ad550,
    0x465aa0, 0x30ada5, 0x5695d0, 0x404ad0, 0x2aa9b3, 0x50a4d0, 0x3ad2b7, 0x5eb250, 0x48b540, 0x33d556
); /* Years 2100-2199 */

var CAN = new Array("Giáp", "Ất", "Bính", "Đinh", "Mậu", "Kỷ", "Canh", "Tân", "Nhâm", "Quý");
var CHI = new Array("Tý", "Sửu", "Dần", "Mão", "Thìn", "Tỵ", "Ngọ", "Mùi", "Thân", "Dậu", "Tuất", "Hợi");
var TUAN = new Array("Chủ nhật", "Thứ hai", "Thứ ba", "Thứ tư", "Thứ năm", "Thứ sáu", "Thứ bảy");
var TIETKHI = new Array("Xuân Phân", "Thanh Minh", "Cốc Vũ", "Lập Hạ", "Tiểu Mãn", "Mang Chủng", "Hạ Chí",
        "Tiểu Thử", "Đại Thử", "Lập Thu", "Xử Thử", "Bạch Lộ", "Thu Phân", "Hàn Lộ", "Sương Giáng", "Lập Đông",
        "Tiểu Tuyết", "Đại Tuyết", "Đông Chí", "Tiểu Hàn", "Đại Hàn", "Lập Xuân", "Vũ Thủy", "Kinh Trập");
var GIO_HD = new Array("110100101100", "001101001011", "110011010010", "101100110100", "001011001101", "010010110011");

/* Create lunar date object, stores (lunar) date, month, year, leap month indicator, and Julian date number */
function LunarDate(dd, mm, yy, leap, jd) {
    this.day = dd;
    this.month = mm;
    this.year = yy;
    this.leap = leap;
    this.jd = jd;
}

function SolarDate(date) {
    this.day = date.getDate();
    this.month = date.getMonth() + 1;
    this.year = date.getFullYear();
}

var PI = Math.PI;

/* Discard the fractional part of a number, e.g., INT(3.2) = 3 */
function INT(d) {
    return Math.floor(d);
}

function jdn(dd, mm, yy) {
    var a = INT((14 - mm) / 12);
    var y = yy + 4800 - a;
    var m = mm + 12 * a - 3;
    var jd = dd + INT((153 * m + 2) / 5) + 365 * y + INT(y / 4) - INT(y / 100) + INT(y / 400) - 32045;
    return jd;
    //return 367*yy - INT(7*(yy+INT((mm+9)/12))/4) - INT(3*(INT((yy+(mm-9)/7)/100)+1)/4) + INT(275*mm/9)+dd+1721029;
}

function jdn2date(jd) {
    var Z, A, alpha, B, C, D, E, dd, mm, yyyy, F;
    Z = jd;
    if (Z < 2299161) {
        A = Z;
    } else {
        alpha = INT((Z - 1867216.25) / 36524.25);
        A = Z + 1 + alpha - INT(alpha / 4);
    }
    B = A + 1524;
    C = INT((B - 122.1) / 365.25);
    D = INT(365.25 * C);
    E = INT((B - D) / 30.6001);
    dd = INT(B - D - INT(30.6001 * E));
    if (E < 14) {
        mm = E - 1;
    } else {
        mm = E - 13;
    }
    if (mm < 3) {
        yyyy = C - 4715;
    } else {
        yyyy = C - 4716;
    }
    return new Array(dd, mm, yyyy);
}

function decodeLunarYear(yy, k) {
    var monthLengths, regularMonths, offsetOfTet, leapMonth, leapMonthLength, solarNY, currentJD, j, mm;
    var ly = new Array();
    monthLengths = new Array(29, 30);
    regularMonths = new Array(12);
    offsetOfTet = k >> 17;
    leapMonth = k & 0xf;
    leapMonthLength = monthLengths[k >> 16 & 0x1];
    solarNY = jdn(1, 1, yy);
    currentJD = solarNY + offsetOfTet;
    j = k >> 4;
    for (i = 0; i < 12; i++) {
        regularMonths[12 - i - 1] = monthLengths[j & 0x1];
        j >>= 1;
    }
    if (leapMonth == 0) {
        for (mm = 1; mm <= 12; mm++) {
            ly.push(new LunarDate(1, mm, yy, 0, currentJD));
            currentJD += regularMonths[mm - 1];
        }
    } else {
        for (mm = 1; mm <= leapMonth; mm++) {
            ly.push(new LunarDate(1, mm, yy, 0, currentJD));
            currentJD += regularMonths[mm - 1];
        }
        ly.push(new LunarDate(1, leapMonth, yy, 1, currentJD));
        currentJD += leapMonthLength;
        for (mm = leapMonth + 1; mm <= 12; mm++) {
            ly.push(new LunarDate(1, mm, yy, 0, currentJD));
            currentJD += regularMonths[mm - 1];
        }
    }
    return ly;
}

function getYearInfo(yyyy) {
    var yearCode;
    if (yyyy < 1900) {
        yearCode = TK19[yyyy - 1800];
    } else if (yyyy < 2000) {
        yearCode = TK20[yyyy - 1900];
    } else if (yyyy < 2100) {
        yearCode = TK21[yyyy - 2000];
    } else {
        yearCode = TK22[yyyy - 2100];
    }
    return decodeLunarYear(yyyy, yearCode);
}

var FIRST_DAY = jdn(25, 1, 1800); // Tet am lich 1800
var LAST_DAY = jdn(31, 12, 2199);

function findLunarDate(jd, ly) {
    if (jd > LAST_DAY || jd < FIRST_DAY || ly[0].jd > jd) {
        return new LunarDate(0, 0, 0, 0, jd);
    }
    var i = ly.length - 1;
    while (jd < ly[i].jd) {
        i--;
    }
    var off = jd - ly[i].jd;
    ret = new LunarDate(ly[i].day + off, ly[i].month, ly[i].year, ly[i].leap, jd);
    return ret;
}

/* Compute the longitude of the sun at any time.
 * Parameter: floating number jdn, the number of days since 1/1/4713 BC noon
 * Algorithm from: "Astronomical Algorithms" by Jean Meeus, 1998
 */
function SunLongitude(jdn) {
    var T, T2, dr, M, L0, DL, lambda, theta, omega;
    T = (jdn - 2451545.0) / 36525; // Time in Julian centuries from 2000-01-01 12:00:00 GMT
    T2 = T * T;
    dr = PI / 180; // degree to radian
    M = 357.52910 + 35999.05030 * T - 0.0001559 * T2 - 0.00000048 * T * T2; // mean anomaly, degree
    L0 = 280.46645 + 36000.76983 * T + 0.0003032 * T2; // mean longitude, degree
    DL = (1.914600 - 0.004817 * T - 0.000014 * T2) * Math.sin(dr * M);
    DL = DL + (0.019993 - 0.000101 * T) * Math.sin(dr * 2 * M) + 0.000290 * Math.sin(dr * 3 * M);
    theta = L0 + DL; // true longitude, degree
    // obtain apparent longitude by correcting for nutation and aberration
    omega = 125.04 - 1934.136 * T;
    lambda = theta - 0.00569 - 0.00478 * Math.sin(omega * dr);
    // Convert to radians
    lambda = lambda * dr;
    lambda = lambda - PI * 2 * (INT(lambda / (PI * 2))); // Normalize to (0, 2*PI)
    return lambda;
}

/* Compute the sun segment at start (00:00) of the day with the given integral Julian day number.
 * The time zone if the time difference between local time and UTC: 7.0 for UTC+7:00.
 * The function returns a number between 0 and 23.
 * From the day after March equinox and the 1st major term after March equinox, 0 is returned.
 * After that, return 1, 2, 3 ...
 */
function getSunLongitude(dayNumber, timeZone) {
    return INT(SunLongitude(dayNumber - 0.5 - timeZone / 24.0) / PI * 12);
}

function getYearCanChi(lunar) {
    return CAN[(lunar.year + 6) % 10] + " " + CHI[(lunar.year + 8) % 12];
}

function getMonthCanChi(lunar) {
    return CAN[(lunar.year * 12 + lunar.month + 3) % 10] + " " + CHI[(lunar.month + 1) % 12] + (lunar.leap == 1 ? " (nhuận)" : "");
}

function getDayCanChi(lunar) {
    return CAN[(lunar.jd + 9) % 10] + " " + CHI[(lunar.jd + 1) % 12];
}

function getTietKhi(lunar, timeZone) {
    return TIETKHI[getSunLongitude(lunar.jd + 1, timeZone)];
}

/*
 * Can cua gio Chinh Ty (00:00) cua ngay voi JDN nay
 */
function getHour0(lunar) {
    return CAN[(lunar.jd - 1) * 2 % 10] + " " + CHI[0];
}

function getDayOfWeek(lunar) {
    return TUAN[(lunar.jd + 1) % 7];
}

function getGioHoangDao(lunar) {
    var chiOfDay = (lunar.jd + 1) % 12;
    var gioHD = GIO_HD[chiOfDay % 6]; // same values for Ty" (1) and Ngo. (6), for Suu and Mui etc.
    var ret = [];
    for (var i = 0; i < 12; i++) {
        if (gioHD.charAt(i) == "1") {
            ret.push({
                text: CHI[i],
                start: (i * 2 + 23) % 24,
                end: (i * 2 + 1) % 24
            });
        }
    }
    return ret;
}

/**********************************************************
 * @@@@@ ICREATIV EVENT CHECKER @@@@@
 **********************************************************/
var MY_TIMEZONE = -(new Date().getTimezoneOffset()) / 60.0;

/**
 * Biến cục bộ của Tasker, truyền từ ngoài vào (%num_days).
 * Số ngày kiểm tra sự kiện, tính từ hôm nay
 */
var NUM_DAYS = parseInt(local('num_days'));

/**
 * Lấy thông tin lịch âm/dương của (numDays) ngày kể từ ngày (startDate)
 */
function getLunarDays(startDate, numDays) {
    var dd = startDate.getDate(),
        mm = startDate.getMonth() + 1,
        yy = startDate.getFullYear(),
        result = [];

    var ly1, ly2, tet1, jd1, jd2, mm1, yy1, result, i;
    if (mm < 12) {
        mm1 = mm + 1;
        yy1 = yy;
    } else {
        mm1 = 1;
        yy1 = yy + 1;
    }
    jd1 = jdn(dd, mm, yy);
    jd2 = jd1 + numDays;
    ly1 = getYearInfo(yy);

    tet1 = ly1[0].jd;

    var solar = new Date(startDate);
    if (tet1 <= jd1) { /* tet(yy) = tet1 < jd1 < jd2 <= 1.1.(yy+1) < tet(yy+1) */
        for (i = jd1; i < jd2; i++) {
            result.push({solar: new SolarDate(solar), lunar: findLunarDate(i, ly1)});
            solar.setDate(solar.getDate() + 1);
        }
    } else if (jd1 < tet1 && jd2 < tet1) { /* tet(yy-1) < jd1 < jd2 < tet1 = tet(yy) */
        ly1 = getYearInfo(yy - 1);
        for (i = jd1; i < jd2; i++) {
            result.push({solar: new SolarDate(solar), lunar: findLunarDate(i, ly1)});
            solar.setDate(solar.getDate() + 1);
        }
    } else if (jd1 < tet1 && tet1 <= jd2) { /* tet(yy-1) < jd1 < tet1 <= jd2 < tet(yy+1) */
        ly2 = getYearInfo(yy - 1);
        for (i = jd1; i < tet1; i++) {
            result.push({solar: new SolarDate(solar), lunar: findLunarDate(i, ly2)});
            solar.setDate(solar.getDate() + 1);
        }
        for (i = tet1; i < jd2; i++) {
            result.push({solar: new SolarDate(solar), lunar: findLunarDate(i, ly1)});
            solar.setDate(solar.getDate() + 1);
        }
    }
    return result;
}

/**
 * Add zero-padding
 */
function lzpad(number, length) {
    let str = Number(number).toString();
    while (str.length < length)
        str = "0" + str;
    return str;
}

var days = getLunarDays(new Date() /* Hôm nay */, NUM_DAYS);
var index  = 0;

/**
 * Kiểm tra từng ngày xem có sự kiện nào định nghĩa trong (EVENT_LIST) đang diễn ra
 */
days.forEach(function(day, offset) {
    var lunar  = day.lunar;
    var solar  = day.solar;
    var events = [];

    EVENT_LIST.forEach(function(event) {
        if ((event[0] == "-" && (event[1] == "*" || event[1] == lunar.day) && (event[2] == "*" || event[2] == lunar.month) && (event[3] == "*" || event[3] == lunar.leap))
            || (event[0] == "+" && (event[1] == "*" || event[1] == solar.day) && (event[2] == "*" || event[2] == solar.month))) {
            var eventText = event[4]
                .replace("{{day_of_week}}", getDayOfWeek(lunar))
                .replace("{{lunar_day}}", lunar.day)
                .replace("{{lunar_month}}", lunar.month + (lunar.leap == 1 ? " (N)" : ""))
                .replace("{{lunar_day_name}}", getDayCanChi(lunar))
                .replace("{{lunar_month_name}}", getMonthCanChi(lunar))
                .replace("{{lunar_year_name}}", getYearCanChi(lunar));

            events.push({
                type: event[0],
                text: eventText
            });
        }
    });

    if (events.length) {
        var dateOffsetText;
        if (offset > 1) {
            dateOffsetText = offset + " ngày tới";
        } else if (offset == 1) {
            dateOffsetText = "Ngày mai";
        } else {
            dateOffsetText = "Hôm nay";
        }

        var result = {
            solar: {
                day: solar.day,
                month: solar.month,
                year: solar.year,
                date: lzpad(solar.day, 2) + "/" +  lzpad(solar.month, 2) + "/" +  lzpad(solar.year, 4)
            },
            lunar: {
                day: lunar.day,
                month: lunar.month,
                date: lzpad(lunar.day, 2) + "/" + lzpad(lunar.month, 2),
                dayText: getDayCanChi(lunar),
                monthText: getMonthCanChi(lunar),
                yearText: getYearCanChi(lunar),
                term: getTietKhi(lunar, MY_TIMEZONE),
                hour0: { text: getHour0(lunar) },
                goldenHours: getGioHoangDao(lunar)
            },
            offset: {
                count: offset,
                text: dateOffsetText
            },
            events: events
        };

        /**
         * Lưu vào biến cục bộ %event() của Tasker
         */
        index++;
        setLocal("event" + index, JSON.stringify(result));
    }
});

Lên danh sách các sự kiện âm dương lịch trong năm

Danh sách các sự kiện tôi lưu ở một file JavaScript khác để thuận tiện cho việc chỉnh sửa. Ở đây tôi để tại thư mục /sdcard/Documents/events.js.

Biến EVENT_LIST là nơi chứa thông tin về các sự kiện. Bạn có thể bổ sung thêm các sự kiện cá nhân (âm lịch hoặc dương lịch) vào đó.

File JavaScript này sẽ được cấu hình để amlich.js load như một library.

/sdcard/Documents/events.js

/**
 * Danh sách các sự kiện
 * +----------+------+-------+------------------+-------------+
 * | Âm/Dương | Ngày | Tháng | Tháng nhuận (ÂL) | Tên sự kiện |
 * +----------+------+-------+------------------+-------------+
 * Dấu "*" mang ý nghĩa là giá trị bất kỳ
 *
 * Tháng nhuận:
 *    0 - Không nhuận
 *    1 - Nhuận
 *    * - Bất kỳ
 */
var EVENT_LIST = [
    // Âm lịch
    ["-",  "1",  "*", "*", "Mồng Một tháng {{lunar_month}}"],
    ["-", "15",  "*", "*", "Rằm tháng {{lunar_month}}"],
    ["-", "15",  "1", "0", "Tết Nguyên Tiêu"],
    ["-",  "3",  "3", "0", "Tết Hàn Thực"],
    ["-", "10",  "3", "0", "Giỗ Tổ Hùng Vương"],
    ["-", "15",  "4", "0", "Lễ Phật Đản"],
    ["-",  "5",  "5", "0", "Tết Đoan Ngọ"],
    ["-", "15",  "7", "0", "Lễ Vu Lan"],
    ["-", "15",  "8", "0", "Tết Trung Thu"],
    ["-", "23", "12", "0", "Lễ ông Công ông Táo"],
    // ...

    // Dương lịch
    ["+",  "1",  "1", "*", "Tết Dương Lịch"],
    ["+",  "9",  "1", "*", "Ngày Học sinh - Sinh viên Việt Nam"],
    ["+",  "3",  "2", "*", "Ngày thành lập Đảng Cộng sản Việt Nam"],
    ["+", "27",  "2", "*", "Ngày Thầy thuốc Việt Nam"],
    ["+",  "8",  "3", "*", "Ngày Quốc tế Phụ nữ"],
    ["+", "20",  "3", "*", "Ngày Quốc tế Hạnh phúc"],
    ["+", "22",  "3", "*", "Ngày Nước sạch Thế giới"],
    ["+", "26",  "3", "*", "Ngày thành lập Đoàn Thanh niên Cộng sản Hồ Chí Minh"],
    ["+", "27",  "3", "*", "Ngày Thể thao Việt Nam"],
    ["+", "21",  "4", "*", "Ngày Sách Việt Nam"],
    ["+", "22",  "4", "*", "Ngày Trái đất"],
    ["+", "30",  "4", "*", "Ngày Giải phóng miền Nam"],
    ["+",  "1",  "5", "*", "Ngày Quốc tế Lao động"],
    ["+",  "7",  "5", "*", "Ngày chiến thắng Điện Biên Phủ"],
    ["+", "15",  "5", "*", "Ngày thành lập Đội Thiếu niên Tiền phong Hồ Chí Minh"],
    ["+", "19",  "5", "*", "Ngày sinh của Chủ tịch Hồ Chí Minh"],
    ["+",  "1",  "6", "*", "Ngày Quốc tế Thiếu nhi"],
    ["+",  "5",  "6", "*", "Ngày môi trường thế giới"],
    ["+", "28",  "6", "*", "Ngày Gia đình Việt Nam"],
    ["+", "27",  "7", "*", "Ngày Thương binh Liệt sĩ"],
    ["+", "19",  "8", "*", "Ngày Cách mạng Tám thành công"],
    ["+",  "2",  "9", "*", "Ngày Quốc khánh"],
    ["+",  "7",  "9", "*", "Ngày thành lập Đài Truyền hình Việt Nam"],
    ["+", "13", "10", "*", "Ngày Doanh nhân Việt Nam"],
    ["+", "20", "10", "*", "Ngày thành lập Hội Phụ nữ Việt Nam"],
    ["+", "20", "11", "*", "Ngày Nhà giáo Việt Nam"],
    ["+", "22", "12", "*", "Ngày thành lập Quân đội Nhân dân Việt Nam"],
    ["+", "25", "12", "*", "Ngày Lễ Giáng Sinh"]
    // ...
];

Tạo Task và Profile để hiển thị các sự kiện

Tôi sẽ tạo một Task với các Action như dưới đây bao gồm hiển thị một Toast về số lượng sự kiện (Chỉ để demo thôi chứ không thiết thực lắm) và một Notification chi tiết về các sự kiện sẽ diễn ra.

Biến %num_days trong Action đầu tiên là số ngày sẽ kiểm tra sự kiện tính cả hôm nay, ở đây tôi để giá trị 1 tức là chỉ ngày hôm nay. Bạn có thể để 7 là tròn một tuần hoặc bao nhiêu tùy thích.

Mỗi một ngày có sự kiện là một JSON Object, thể hiện trong biến %day khi duyệt với vòng lặp For. Ta có thể truy cập trực tiếp các trường của biến này như trong Flash Action, hoặc dùng JavaScriptlet Action để có những xử lý phức tạp hơn.

Task: Show Events

ActionSettings
Variable SetName: %num_days
To: 1
JavaScriptPath: Documents/amlich.js
Library: file:///sdcard/Documents/events.js
Auto Exit: yes
ForVariable: %day
Items: %event()
Structure Output (JSON, etc): yes
FlashText: Có %day.events(#) sự kiện trong %day.offset.text
JavaScriptletCode:
var d = JSON.parse(local("day"))
var title = d.offset.text + ", " + d.solar.date + "(" + d.lunar.date + " ÂL)"
var text = d.events.map(e => "🎉 " + e.text).join("\n")

setLocal("title", title)
setLocal("text", text)
Auto Exit: yes
NotifyTitle: %title
Text: %text
Category: Tasker
End For

Sau đó ta có thể tạo một Profile để gọi Task này hàng ngày để hiện thông báo về các sự kiện trong những ngày tới.

Profile: Events Checker

ConditionValue
TimeFrom: 05:00
To: 12:00
Task: Show Events

Phản hồi về bài viết

Cùng thảo luận chút nhỉ!

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.