如何在不使用任何 library/package 的情况下实现转换纪元时间戳的例程?
How do I implement a routine to convert epoch timestamp without using any library/package?
我正在实施一个例程,将 Epoch 时间戳转换为年、月、日、小时、分钟和秒。
重要说明:我不能使用任何现有的 Java 库,因为此例程用作测试程序,稍后将在 GPU 中实现。因此不建议使用Localdate、ZonedDateTime、Datetime等。例程必须使用普通数据类型和基本算术运算。
这些是规格:
- 输入数据是
UNIX Epoch timestamp in seconds
.
- 输出数据是一个带有
year/month/day hour:minute
. 的字符串
- 日期时间限制在
January 1st 1990
到 January 1st 2050
之间。
No leap seconds
因为输入数据是 UNIX 纪元时间戳。
例程只处理基于这些条件的有效纪元时间戳。
这是我尝试过的方法,我将其作为可复制的 Java 程序包括在内。
我有一个适用于 2000 年 1 月 1 日以上日期的有效例程:例程 epochToDatetimeBase2000
。
我正在尝试编写一个适用于 1990 年 1 月 1 日以上日期的模块,例程 epochToDatetimeBase1990
,但不起作用。
这是程序的完整可复制源代码,包括例程和测试数据:
public class MyClass {
public static String epochToDatetimeBase2000(int epoch) {
int epochOriginal = epoch;
epoch = epoch - 946684800; // 946684800 is Epoch for Saturday, 1 January 2000 00:00:00
int[] days = new int[]{
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
366, 397, 425, 456, 486, 517, 547, 578, 609, 639, 670, 700,
731, 762, 790, 821, 851, 882, 912, 943, 974,1004,1035,1065,
1096,1127,1155,1186,1216,1247,1277,1308,1339,1369,1400,1430
};
int second = epoch % 60;
epoch = epoch / 60;
int minute = epoch % 60;
epoch = epoch / 60;
int hour = epoch % 24;
epoch = epoch / 24;
int years = epoch/(365*4+1)*4;
epoch %= 365*4+1;
int year;
for (year=3; year>0; year=year-1)
{
if (epoch >= days[year*12])
break;
}
int month;
for (month=11; month>0; month--)
{
if (epoch >= days[year*12 + month])
break;
}
int yearVal = years+year;
int monthVal = month+1;
int dayVal = epoch-days[year*12 + month]+1;
String strDatetime = String.format("%d %02d/%02d/%02d %02d:%02d.%02d", epochOriginal, dayVal, monthVal, 2000+yearVal, hour, minute, second); // Float value.
return strDatetime;
}
public static String epochToDatetimeBase1990(int epoch) {
int epochOriginal = epoch;
epoch = epoch - 631152000; // 631152000 is Epoch for Monday, 1 January 1990 00:00:00
int[] days = new int[]{
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
366, 397, 425, 456, 486, 517, 547, 578, 609, 639, 670, 700,
731, 762, 790, 821, 851, 882, 912, 943, 974,1004,1035,1065,
1096,1127,1155,1186,1216,1247,1277,1308,1339,1369,1400,1430
};
int second = epoch % 60;
epoch = epoch / 60;
int minute = epoch % 60;
epoch = epoch / 60;
int hour = epoch % 24;
epoch = epoch / 24;
int years = epoch/(365*4+1)*4;
epoch %= 365*4+1;
int year;
for (year=3; year>0; year=year-1)
{
if (epoch >= days[year*12])
break;
}
int month;
for (month=11; month>0; month--)
{
if (epoch >= days[year*12 + month])
break;
}
int yearVal = years+year;
int monthVal = month+1;
int dayVal = epoch-days[year*12 + month]+1;
String strDatetime = String.format("%d %02d/%02d/%02d %02d:%02d.%02d", epochOriginal, dayVal, monthVal, 1990+yearVal, hour, minute, second); // Float value.
return strDatetime;
}
public static void main(String args[]) {
// USING BASE 2000
System.out.println(epochToDatetimeBase2000(978307200)); // Epoch timestamp: 978307200 Date and time (GMT): Monday, 1 January 2001 00:00:00
System.out.println(epochToDatetimeBase2000(631152000)); // Epoch timestamp: 631152000 Date and time (GMT): Tuesday, 1 January 1990 00:00:00
System.out.println(epochToDatetimeBase2000(662688000)); // Epoch timestamp: 662688000 Date and time (GMT): Tuesday, 1 January 1991 00:00:00
// USING BASE 1990
System.out.println(epochToDatetimeBase1990(978307200)); // Epoch timestamp: 978307200 Date and time (GMT): Monday, 1 January 2001 00:00:00
System.out.println(epochToDatetimeBase1990(631152000)); // Epoch timestamp: 631152000 Date and time (GMT): Tuesday, 1 January 1990 00:00:00
System.out.println(epochToDatetimeBase1990(662688000)); // Epoch timestamp: 662688000 Date and time (GMT): Tuesday, 1 January 1991 00:00:00
}
}
这是输出:
978307200 01/01/2001 00:00.00
631152000 -729/01/1992 00:00.00
662688000 -364/01/1992 00:00.00
978307200 01/01/2001 00:00.00
631152000 01/01/1990 00:00.00
662688000 31/12/1990 00:00.00 <- SHALL BE 1 January 1991 00:00:00
您的 days
数组中 epochToDatetimeBase1990
是否有误?我注意到这些值与 epochToDatetimeBase2000
中的值完全相同。 2000 年是闰年,但 1990 年不是!所以闰年在数组中的不同位置开始。我认为 days
应该像 epochToDatetimeBase1990
中这样定义:
int[] days = new int[]{
// 1990 is NOT a leap year
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
365, 396, 424, 455, 485, 516, 546, 577, 608, 638, 669, 699,
// 1992 is a leap year here
730, 761, 790, 821, 851, 882, 912, 943, 974,1004,1035,1065,
1096,1127,1155,1186,1216,1247,1277,1308,1339,1369,1400,1430
};
我准备了另一种解决方案。请看一下。
此外,这对任何其他年份边界都有帮助,因为只需更改 START_YEAR、START_EPOCH 和 END_YEAR。
final static int START_YEAR = 1990;
final static long START_EPOCH = 631152000;
final static int END_YEAR = 2050;
final static int[] MONTH_DAYS = new int[]{31,28,31,30,31,30,31,31,30,31,30,31};
private static void convertEpochToDateTime(long epoch){
long relativeEpoch = epoch-START_EPOCH;
int[] daysAndRemainingSeconds = getTotalDaysAndRemainingSeconds(relativeEpoch);
int remainingSeconds = daysAndRemainingSeconds[1];
int[] time = convertSecondsToTime(remainingSeconds);
int totalDays = daysAndRemainingSeconds[0];
int[] yearAndRemainingDays = getYearAndRemainingDays(totalDays);
int year = yearAndRemainingDays[0];
int remainingDays = yearAndRemainingDays[1];
int[] monthAndDays =getMonthsAndRemaingDays(remainingDays,isLeapYear(year));
String strDatetime = String.format("%d %02d/%02d/%02d %02d:%02d.%02d", epoch, monthAndDays[1]+1, monthAndDays[0], year, time[0], time[1], time[2]);
System.out.println(String.valueOf(strDatetime));
}
private static int[] getTotalDaysAndRemainingSeconds(long seconds){
return new int[]{(int)seconds/86400,(int)seconds%86400};
}
private static int[] getYearAndRemainingDays(int days){
int tmpDays = 0;
for(int year=START_YEAR;year<=END_YEAR;year++){
int daysInYear = isLeapYear(year)?366:365;
if(tmpDays+daysInYear>days) return new int[]{year,days-tmpDays};
tmpDays +=daysInYear;
}
return new int[]{0,0};
}
private static boolean isLeapYear(int year){
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
private static int[] convertSecondsToTime(int seconds){
int sec = seconds % 60;
int hr = seconds / 60;
int min = hr % 60;
hr = hr / 60;
return new int[]{hr,min,sec};
}
private static int[] getMonthsAndRemaingDays(int days,boolean leapYear){
int tmdDays = 0;
for(int month=1;month<=12;month++){
int daysInThisMonth = MONTH_DAYS[month-1]+(month==2 && leapYear?1:0);
if(tmdDays+daysInThisMonth>days) return new int[]{month,days-tmdDays};
tmdDays+=daysInThisMonth;
}
return new int[]{12,0};
}
我正在实施一个例程,将 Epoch 时间戳转换为年、月、日、小时、分钟和秒。
重要说明:我不能使用任何现有的 Java 库,因为此例程用作测试程序,稍后将在 GPU 中实现。因此不建议使用Localdate、ZonedDateTime、Datetime等。例程必须使用普通数据类型和基本算术运算。
这些是规格:
- 输入数据是
UNIX Epoch timestamp in seconds
. - 输出数据是一个带有
year/month/day hour:minute
. 的字符串
- 日期时间限制在
January 1st 1990
到January 1st 2050
之间。 No leap seconds
因为输入数据是 UNIX 纪元时间戳。
例程只处理基于这些条件的有效纪元时间戳。
这是我尝试过的方法,我将其作为可复制的 Java 程序包括在内。
我有一个适用于 2000 年 1 月 1 日以上日期的有效例程:例程 epochToDatetimeBase2000
。
我正在尝试编写一个适用于 1990 年 1 月 1 日以上日期的模块,例程 epochToDatetimeBase1990
,但不起作用。
这是程序的完整可复制源代码,包括例程和测试数据:
public class MyClass {
public static String epochToDatetimeBase2000(int epoch) {
int epochOriginal = epoch;
epoch = epoch - 946684800; // 946684800 is Epoch for Saturday, 1 January 2000 00:00:00
int[] days = new int[]{
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
366, 397, 425, 456, 486, 517, 547, 578, 609, 639, 670, 700,
731, 762, 790, 821, 851, 882, 912, 943, 974,1004,1035,1065,
1096,1127,1155,1186,1216,1247,1277,1308,1339,1369,1400,1430
};
int second = epoch % 60;
epoch = epoch / 60;
int minute = epoch % 60;
epoch = epoch / 60;
int hour = epoch % 24;
epoch = epoch / 24;
int years = epoch/(365*4+1)*4;
epoch %= 365*4+1;
int year;
for (year=3; year>0; year=year-1)
{
if (epoch >= days[year*12])
break;
}
int month;
for (month=11; month>0; month--)
{
if (epoch >= days[year*12 + month])
break;
}
int yearVal = years+year;
int monthVal = month+1;
int dayVal = epoch-days[year*12 + month]+1;
String strDatetime = String.format("%d %02d/%02d/%02d %02d:%02d.%02d", epochOriginal, dayVal, monthVal, 2000+yearVal, hour, minute, second); // Float value.
return strDatetime;
}
public static String epochToDatetimeBase1990(int epoch) {
int epochOriginal = epoch;
epoch = epoch - 631152000; // 631152000 is Epoch for Monday, 1 January 1990 00:00:00
int[] days = new int[]{
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
366, 397, 425, 456, 486, 517, 547, 578, 609, 639, 670, 700,
731, 762, 790, 821, 851, 882, 912, 943, 974,1004,1035,1065,
1096,1127,1155,1186,1216,1247,1277,1308,1339,1369,1400,1430
};
int second = epoch % 60;
epoch = epoch / 60;
int minute = epoch % 60;
epoch = epoch / 60;
int hour = epoch % 24;
epoch = epoch / 24;
int years = epoch/(365*4+1)*4;
epoch %= 365*4+1;
int year;
for (year=3; year>0; year=year-1)
{
if (epoch >= days[year*12])
break;
}
int month;
for (month=11; month>0; month--)
{
if (epoch >= days[year*12 + month])
break;
}
int yearVal = years+year;
int monthVal = month+1;
int dayVal = epoch-days[year*12 + month]+1;
String strDatetime = String.format("%d %02d/%02d/%02d %02d:%02d.%02d", epochOriginal, dayVal, monthVal, 1990+yearVal, hour, minute, second); // Float value.
return strDatetime;
}
public static void main(String args[]) {
// USING BASE 2000
System.out.println(epochToDatetimeBase2000(978307200)); // Epoch timestamp: 978307200 Date and time (GMT): Monday, 1 January 2001 00:00:00
System.out.println(epochToDatetimeBase2000(631152000)); // Epoch timestamp: 631152000 Date and time (GMT): Tuesday, 1 January 1990 00:00:00
System.out.println(epochToDatetimeBase2000(662688000)); // Epoch timestamp: 662688000 Date and time (GMT): Tuesday, 1 January 1991 00:00:00
// USING BASE 1990
System.out.println(epochToDatetimeBase1990(978307200)); // Epoch timestamp: 978307200 Date and time (GMT): Monday, 1 January 2001 00:00:00
System.out.println(epochToDatetimeBase1990(631152000)); // Epoch timestamp: 631152000 Date and time (GMT): Tuesday, 1 January 1990 00:00:00
System.out.println(epochToDatetimeBase1990(662688000)); // Epoch timestamp: 662688000 Date and time (GMT): Tuesday, 1 January 1991 00:00:00
}
}
这是输出:
978307200 01/01/2001 00:00.00
631152000 -729/01/1992 00:00.00
662688000 -364/01/1992 00:00.00
978307200 01/01/2001 00:00.00
631152000 01/01/1990 00:00.00
662688000 31/12/1990 00:00.00 <- SHALL BE 1 January 1991 00:00:00
您的 days
数组中 epochToDatetimeBase1990
是否有误?我注意到这些值与 epochToDatetimeBase2000
中的值完全相同。 2000 年是闰年,但 1990 年不是!所以闰年在数组中的不同位置开始。我认为 days
应该像 epochToDatetimeBase1990
中这样定义:
int[] days = new int[]{
// 1990 is NOT a leap year
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
365, 396, 424, 455, 485, 516, 546, 577, 608, 638, 669, 699,
// 1992 is a leap year here
730, 761, 790, 821, 851, 882, 912, 943, 974,1004,1035,1065,
1096,1127,1155,1186,1216,1247,1277,1308,1339,1369,1400,1430
};
我准备了另一种解决方案。请看一下。
此外,这对任何其他年份边界都有帮助,因为只需更改 START_YEAR、START_EPOCH 和 END_YEAR。
final static int START_YEAR = 1990;
final static long START_EPOCH = 631152000;
final static int END_YEAR = 2050;
final static int[] MONTH_DAYS = new int[]{31,28,31,30,31,30,31,31,30,31,30,31};
private static void convertEpochToDateTime(long epoch){
long relativeEpoch = epoch-START_EPOCH;
int[] daysAndRemainingSeconds = getTotalDaysAndRemainingSeconds(relativeEpoch);
int remainingSeconds = daysAndRemainingSeconds[1];
int[] time = convertSecondsToTime(remainingSeconds);
int totalDays = daysAndRemainingSeconds[0];
int[] yearAndRemainingDays = getYearAndRemainingDays(totalDays);
int year = yearAndRemainingDays[0];
int remainingDays = yearAndRemainingDays[1];
int[] monthAndDays =getMonthsAndRemaingDays(remainingDays,isLeapYear(year));
String strDatetime = String.format("%d %02d/%02d/%02d %02d:%02d.%02d", epoch, monthAndDays[1]+1, monthAndDays[0], year, time[0], time[1], time[2]);
System.out.println(String.valueOf(strDatetime));
}
private static int[] getTotalDaysAndRemainingSeconds(long seconds){
return new int[]{(int)seconds/86400,(int)seconds%86400};
}
private static int[] getYearAndRemainingDays(int days){
int tmpDays = 0;
for(int year=START_YEAR;year<=END_YEAR;year++){
int daysInYear = isLeapYear(year)?366:365;
if(tmpDays+daysInYear>days) return new int[]{year,days-tmpDays};
tmpDays +=daysInYear;
}
return new int[]{0,0};
}
private static boolean isLeapYear(int year){
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
private static int[] convertSecondsToTime(int seconds){
int sec = seconds % 60;
int hr = seconds / 60;
int min = hr % 60;
hr = hr / 60;
return new int[]{hr,min,sec};
}
private static int[] getMonthsAndRemaingDays(int days,boolean leapYear){
int tmdDays = 0;
for(int month=1;month<=12;month++){
int daysInThisMonth = MONTH_DAYS[month-1]+(month==2 && leapYear?1:0);
if(tmdDays+daysInThisMonth>days) return new int[]{month,days-tmdDays};
tmdDays+=daysInThisMonth;
}
return new int[]{12,0};
}