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 ...
随机推荐
- C语言: 预处理
1. 字符映射 键盘有多种标准规格,例如常用的IBM 104键盘标准,然而不是所有键盘都能打出像#这样的符号,因此C语言的预处理引入了字符映射机制.如果程序员要求,预处理会按照约定对源代码中的字符进行 ...
- GJM :C#开发 异步处理是目的,多线程是手段
但是BeginAccept和EndAccept不就是system.net.socket封装好的异步socket吗如果用多线程来实现的话那就不叫异步了吧 1.再次强调,异步是目的,多线程是手段. 所谓异 ...
- 使用MyEclipse 开发struts2框架结构详细教程——以登录为例
1.首先建立Web Project,名称为:struts2 ,然后选择Java EE6.0,点击Finish. 2.右击“struts”选择MyEclipse->Add Struts Capab ...
- hadoop 集群的配置
在经过几天折腾,终于将hadoop环境搭建成功,整个过程中遇到各种坑,反复了很多遍,光虚拟机就重新安装了4.5次,接下来就把搭建的过程详细叙述一下 0.相关工具: 1,系统环境说明: 我这边给出我的集 ...
- 《移动端浏览器Touch事件判断手指滑动方向方法》
$("body").on("touchstart", function(e) { e.preventDefault(); startX = e. ...
- 接入统计Crash的工具Crashlytics-ios
1. 注册账户 登录网站 https://get.fabric.io/ 来注册新的账户 2. account confirmed之后就出现相应的设置页面,设置你的team的名称 3. 出现页面提示下载 ...
- OC笔记一:Objective-C简介
1.OC简介 全称:Objective-C,是扩充C的面向对象编程语言,主要用于iOS和Mac OS开发. C语言的基础上,增加了一层最小的面向对象语法 完全兼容C语言 可以在OC代码中混入C语言代码 ...
- SharePoint 2013 文档库中PPT转换PDF
通过使用 PowerPoint Automation Services,可以从 PowerPoint 二进制文件格式 (.ppt) 和 PowerPoint Open XML 文件格式 (.pptx) ...
- iOS9请求https问题-记录
iOS9 开始苹果将HTTP全改为HTTPS了,所以出现网络请求失败问题,解决办法: 1.改回HTTP: 在info.plist文件中添加一个Key:NSAppTransportSecurity(字典 ...
- 【读书笔记】100个Switf必备tips
声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.com 农民伯伯: http://over140.cnblogs.com 正文 1.Selector 在Swi ...