1

如何在 Perl 中将十进制转换为 MK 时间。

我得到这个文件:

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 秒

4

2 回答 2

1

在 Perl 中,您可以使用localtime函数,或者更好的想法是使用许多日期/时间处理模块之一,这些模块更方便并允许更复杂的计算(例如DateTime)。

当地时间

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

本地时间/mktime

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 Aug 20 09:17:25 1983(小时取决于时区,更改时区以localtime使用tzset)而不是OP 中建议的Sun Jan 1 00:00:00 。

于 2013-10-25T08:31:34.743 回答
1

现代(即至少 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
于 2013-10-25T09:15:51.057 回答