time.c 的Java实现(从timestamp计算年月日时分秒等数值)
time.c的Java实现
public class GMT {
public static final int EPOCH_YEAR = 1970;
public static final int[][] MONTH_DAYS = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
public static final long MSECS_DAY = 1000*3600*24L;
private long timestamp;
private int mil;
private int sec;
private int min;
private int hour;
private int wday;
private int mday;
private int yday;
private int mon;
private int year;
public GMT(long timestamp, long shift) {
this.timestamp = timestamp + shift;
long dayclock = (this.timestamp % MSECS_DAY) / 1000L;
long dayno = this.timestamp / MSECS_DAY;
mil = (int) (this.timestamp % 1000L);
sec = (int) (dayclock % 60);
min = (int) ((dayclock % 3600) / 60);
hour = (int) (dayclock / 3600);
wday = (int) ((dayno + 4) % 7);
while (dayno >= yearDays(EPOCH_YEAR + year)) {
dayno -= yearDays(EPOCH_YEAR + year);
year++;
}
year = EPOCH_YEAR + year;
yday = (int)dayno;
int[] monthDays = leapYear(year) ? MONTH_DAYS[1] : MONTH_DAYS[0];
while (dayno >= monthDays[mon]) {
dayno -= monthDays[mon];
mon++;
}
mon++;
mday = (int)dayno + 1;
}
public long toLongInteger() {
return year * 10000000000000L
+ mon * 100000000000L
+ mday * 1000000000L
+ hour * 10000000L
+ min * 100000L
+ sec * 1000L
+ mil;
}
private static int yearDays(int year) {
return leapYear(year) ? 366 : 365;
}
private static boolean leapYear(int year) {
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
public int getMil() { return mil; }
public void setMil(int mil) { this.mil = mil; }
public int getSec() { return sec; }
public void setSec(int sec) { this.sec = sec; }
public int getMin() { return min; }
public void setMin(int min) { this.min = min; }
public int getHour() { return hour; }
public void setHour(int hour) { this.hour = hour; }
public int getWday() { return wday; }
public void setWday(int wday) { this.wday = wday; }
public int getMday() { return mday; }
public void setMday(int mday) { this.mday = mday; }
public int getYday() { return yday; }
public void setYday(int yday) { this.yday = yday; }
public int getMon() { return mon; }
public void setMon(int mon) { this.mon = mon; }
public int getYear() { return year; }
public void setYear(int year) { this.year = year; }
public static void main(String[] args) {
long start = System.currentTimeMillis();
int total = 500000;
for (int i = 0; i < total; i ++) {
GMT gmt = new GMT(System.currentTimeMillis(), 1000L*3600*8);
System.out.println(gmt.toLongInteger());
}
long duration = System.currentTimeMillis() - start;
System.out.println("Total: " + duration + "ms, " + total/duration + "/ms");
}
}
可以作为Snowflake ID generator的前缀生成器, 好处是易于业务手工识别, 缺点是速度较慢, 与直接使用二进制的机制差一个数量级(sf默认实现是20k/ms, 这个只有2k/ms).
在带I/O的情况下, 能达到150/ms的生成速度, 比使用SimpleDateFormat的效率高很多, 还是可以使用的, 如果使用SimpleDateFormat的话, 只有30/ms的速度.
Update:
用这个改造出来的...TimeflakeId是类似于这样的
public class TimeflakeId {
private final static int SEQUENCE_MASK = 999;
private final RecyclableAtomicInteger atomic = new RecyclableAtomicInteger();
private long lastTimestamp = -1L;
private long lastTsFormatted = -1L;
public long nextId() {
long timestamp = millisecond();
if (timestamp < lastTimestamp) {
throw new IllegalArgumentException(
String.format("Wait for %d milliseconds", lastTimestamp - timestamp));
}
if (lastTimestamp == timestamp) {
int sequence = atomic.incrementAndRecycle(SEQUENCE_MASK);
if (sequence == 0) {
timestamp = waitTilNextMillis(lastTimestamp);
lastTimestamp = timestamp;
lastTsFormatted = getFormattedTimestamp();
}
return lastTsFormatted * 1000 + sequence;
} else {
atomic.set(0);
lastTimestamp = timestamp;
lastTsFormatted = getFormattedTimestamp();
return lastTsFormatted * 1000;
}
}
private long waitTilNextMillis(final long lastTimestamp) {
long timestamp;
for (;;) {
timestamp = this.millisecond();
if (timestamp > lastTimestamp) {
return timestamp;
}
}
}
private long millisecond() {
return System.currentTimeMillis();
}
public static final int EPOCH_YEAR = 1970;
public static final long[][] MONTH_DAYS = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
public static final long MSECS_DAY = 1000*3600*24L;
private long getFormattedTimestamp() {
long ts = lastTimestamp + 1000L*3600*8;
long dayclock = (ts % MSECS_DAY) / 1000L;
long dayno = ts / MSECS_DAY;
long mil = ts % 1000L;
long sec = dayclock % 60;
long min = (dayclock % 3600) / 60;
long hour = dayclock / 3600;
long year = 0;
while (dayno >= yearDays(EPOCH_YEAR + year)) {
dayno -= yearDays(EPOCH_YEAR + year);
year++;
}
long[] monthDays = leapYear(EPOCH_YEAR + year) ? MONTH_DAYS[1] : MONTH_DAYS[0];
int mon = 0;
while (dayno >= monthDays[mon]) {
dayno -= monthDays[mon];
mon++;
}
mon++;
long mday = dayno + 1;
return ((year > 30)? year - 30 : year + 70) * 10000000000000L
+ mon * 100000000000L
+ mday * 1000000000L
+ hour * 10000000L
+ min * 100000L
+ sec * 1000L
+ mil;
}
private static int yearDays(long year) {
return leapYear(year) ? 366 : 365;
}
private static boolean leapYear(long year) {
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
public static void main(String[] args) {
TimeflakeId worker = new TimeflakeId();
long start = System.currentTimeMillis();
int total = 50000;
for (int i = 0; i < total; i ++) {
//System.out.println(worker.nextId());
worker.nextId();
}
long duration = System.currentTimeMillis() - start;
System.out.println("Total: " + duration + "ms, " + total/duration + "/ms");
}
}
RecyclableAtomicInteger 的实现
public class RecyclableAtomicInteger extends AtomicInteger
{
/**
* Atomically increments by one the current value, or return
* to zero if the value exceeds threshold
*
* @return the updated value
*/
public final int incrementAndRecycle(int threshold) {
for (;;) {
int current = get();
int next = (current + 1) % threshold;
if (compareAndSet(current, next))
return next;
}
}
}
time.c 的Java实现(从timestamp计算年月日时分秒等数值)的更多相关文章
- [置顶] java得到前一个月的年月日时分秒
import java.util.Calendar; /** * 得到前一个月的年月日时分秒 * @author Mr.hu * 2013-6-28上午12:00:35 * Class Explain ...
- java 获取当前时间及年月日时分秒
java代码如下: package test; import java.text.SimpleDateFormat; import java.util.Calendar; import java.ut ...
- java.sql.date 插入数据库没有时分秒
java.sql.date 插入数据库没有时分秒 把java中实体类的sql.date类型改成java.sql.Timestamp类型即可 util.date 转 Timestamp: java.sq ...
- C#计算两个时间的时间差,精确到年月日时分秒
喏,计算两个时间的时间差,精确到年月日时分秒 看起来比较笨的方法了,不知道有没有改进 DateTime d1 = new DateTime(2016, 4, 1, 0, 0, 0); DateTime ...
- java中Date无法获取数据库时分秒的问题
数据库使用的字段是timestamp(6),在数据库看的时候明明时分秒是有的,然而通过rs.getDate()获取出来的时候时分秒就没有了,查了一下资料终于解决了,这里有一个重要的知识点,java ...
- java Date获取 年月日时分秒
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...
- 2018.2.2 java中的Date如何获取 年月日时分秒
package com.util; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; pub ...
- Java输出当前的日期(年月日时分秒毫秒)
package test.remote.tools.combine; import java.text.SimpleDateFormat; import java.util.Calendar; imp ...
- java日期格式(年月日时分秒毫秒)
package test.remote.tools.combine; import java.text.SimpleDateFormat; import java.util.Calendar; imp ...
随机推荐
- Xdebug文档(四)函数跟踪
Xdebug能让你把所有函数调用,包括参数和返回值以不同的格式记录到文件中. 这些号称“函数跟踪”功能能帮助你面对一个新应用程序,亦或者在程序运行时你想弄清楚它在做什么.函数跟踪功能可以选择性地显示函 ...
- Maven学习随笔一——Maven安装报错处理(mvn -v, 提示不是内部命令的问题)
今天心血来潮学习maven,可是光安装就花了个把小时,好坑有木有! 安装过程可百度,各种经贴,不详. 控制台输入 mvn -v ,如果报错,很可能是你的java/maven的环境变量配置出了点问题: ...
- js中的位运算
按位运算符是把操作数看作一系列单独的位,而不是一个数字值.所以在这之前,不得不提到什么是"位": 数值或字符在内存内都是被存储为0和 1的序列,每个0和1被称之为1个位,比如说10 ...
- xml与datatable类型互换
//已测 private DataTable ConvertXMLToDataSet(string xmlData) { StringReader stream = null; XmlTextRead ...
- MFC-简单的函数使用
1. MessageBox(str);很简单的一个函数,该函数参数为字符串.用来弹出一个窗口显示str的内容,str为一个字符串. 2. UpdateData();该函数是vc++中处理控件变量的 ...
- JavaScript基本语法(四)
一. JavaScript 函数 1.函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块.我们可以将一些常用的代码封装成函数,待用到的时候就能直接调用使用.利用函数可以使代码的组织结构 ...
- C# 生成字符串的 CheckSum
C# 生成字符串的 CheckSum private static string CheckSum(string message) { char[] chars = message.ToCharArr ...
- iOS之There was an internal API error错误
There was an internal API error. 错误原因:把Product Name作为程序名称,程序名称错乱 解决方法:检查Product Name, 不要包含中文以及特殊字符.在 ...
- h5滑动方向、手机拖动层
做h5时需对手指滑动方向判断及拖动浮动层,本文代码适用于手机端h5页面,pc页面可使用onMouseDown.onMouseUp.onMouseMove.(本方法仅为功能实现原理和演示,可根据自己的需 ...
- Oracle 11g数据库详细安装步骤图解
1.先到Oracle官网上下载11g oracle Database 11g 第 2 版 (11.2.0.1.0) 标准版.标准版 1 以及企业版 适用于 Microsoft Windows (x64 ...