МК Время в перле

Как я могу преобразовать десятичное время в MK Time в Perl.

Я получаю эту документацию:

codes below are time decoding and encoding, for your reference

static const unsigned char rtc_days_in_month[] = {
    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

static const unsigned short rtc_ydays[2][13] = {
    /* Normal years */
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
    /* Leap years */
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};

#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400))

u32 Mktime (u32 year, u32 mon,  u32  day, u32  hour,u32  min, u32  sec)
{
    if (0 >= (int) (mon -= 2)){    /**//* 1..12 -> 11,12,1..10 */
         mon += 12;      /**//* Puts Feb last since it has leap day */
         year -= 1;
    }

    return ((((unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) 
            + year*365 - 719499
          )*24 + hour
       )*60 + min
    )*60 + sec;
}

/*
 * The number of days in the month.
 */
s16 rtc_month_days(u16 month, u16 year)
{
    return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1);
}


/*
 * The number of days since January 1. (0 to 365)
 */
s16 rtc_year_days(u16 day, u16 month, u16 year)
{
    return rtc_ydays[LEAP_YEAR(year)][month] + day-1;
}

void rtc_time_to_tm(u32 time, rtc_time *tm)
{
    s16 days, month, year;

    s16 newdays;

    days = time / 86400;
    time -= days * 86400;

    /* day of the week, 1970-01-01 was a Thursday */
    tm->tm_wday = (days + 4) % 7;

    year = 1970 + days / 365;
    days -= (year - 1970) * 365
        + LEAPS_THRU_END_OF(year - 1)
        - LEAPS_THRU_END_OF(1970 - 1);
    if (days < 0) {
        year -= 1;
        days += 365 + LEAP_YEAR(year);
    }
    tm->tm_year = year - 1900;
    tm->tm_yday = days + 1;

    for (month = 0; month < 11; month++) {
        newdays = days - rtc_month_days(month, year);
        if (newdays < 0)
            break;
        days = newdays;
    }
    tm->tm_mon = month + 1;
    tm->tm_mday = days + 1;

    tm->tm_hour = time / 3600;
    time -= tm->tm_hour * 3600;
    tm->tm_min = time / 60;
    tm->tm_sec = time - tm->tm_min * 60;
    tm->tm_year += 1900;
}



u32 Pro_Mktime (u32 year, u32 mon,  u32  day, u32  hour,u32  min, u32  sec)
{   
        u32 baseMk=0;
    u32 mk=0;
    u32 retMk=0;

    baseMk=Mktime(2000,1,1,0,0,0);
    mk=Mktime(year,mon,day, hour,min,sec);
    retMk=mk-baseMk;
    return retMk;

}

void Pro_Localtime (u32 mktime, rtc_time *tm)
{   
    struct tm  *tblock;
        u32 baseMk=0;
    u32 mk=0;
    baseMk=Mktime(2000,1,1,0,0,0);
    mk=mktime+baseMk;
    rtc_time_to_tm(mk,tm);
}

Мне нужно продолжить это в perl, а не в java.

Как десятичное число 430208245 преобразовать в 2000 год, месяц 1, день 1, 0 часов, 1 день, 0 часов, 0 минут, 0 секунд


person bernamaxim    schedule 25.10.2013    source источник
comment
430208245 = Сб 20 августа 10:17:25 1983, не так ли?   -  person Suic    schedule 25.10.2013


Ответы (2)


Самый простой подход к современному (т.е. не ниже 5.10) Perl — использовать Time::Piece. Этот модуль переопределяет функцию localtime, так что теперь он возвращает вам полезный объект.

use Time::Piece;
my $time = localtime(430208245);

Затем вы можете получить доступ к отдельным элементам времени и даты:

say $time->year; # 1983
say $time->mon; # 8

Распечатайте все:

say $time; # Sat Aug 20 07:17:25 1983

Или используйте метод strftime, чтобы получить его в пользовательском формате:

say $time->strftime("%Y-%m-%dT%H:%M:%S"); # 1983-08-20T07:17:25
person Dave Cross    schedule 25.10.2013

В Perl вы можете использовать функцию localtime, или еще лучше использовать одну из многих Модули обработки даты/времени, которые более удобны и позволяют выполнять более сложные вычисления (например, ДатаВремя).

местное время:

my @mabbr=qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my @dabbr=qw(Sun Mon Tue Wed Thu Fri Sat);
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(430208245);
$year+=1900;
printf '%s %s %d %02d:%02d:%02d %d',$dabbr[$wday],$mabbr[$mon],$mday,$hour,$min,$sec,$year;
#prints Sat Aug 20 09:17:25 1983

местное/мквремя:

use POSIX qw(mktime ctime);
my $t=mktime(localtime(430208245));
print ctime($t);
#prints Sat Aug 20 09:17:25 1983

Дата/время:

use DateTime;
my $dt=DateTime->from_epoch(epoch=>430208245,time_zone=>'local');
printf '%s %s %d %s %d',$dt->day_abbr,$dt->month_abbr,$dt->day,$dt->hms,$dt->year;
#prints Sat Aug 20 09:17:25 1983

PS. Как правильно заметил Suic, 430208245 — это Sat 20 Aug 09:17:25 1983 (час зависит от часового пояса, чтобы изменить часовой пояс на localtime, используйте tzset), а не Sun 1 Jan 00:00:00, как предлагается в ОП.

person psxls    schedule 25.10.2013