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 ...
随机推荐
- ERROR LazyInitializationException:19 - failed to lazily initialize a collection of role: com.goodfan.entity.BeanA.beanB, no session or session was closed
1. 问题, 当使用JSONArray.fromObject(List<BeanA>)时, beanA中含有BeanB的属性beanB时,会报这个错 2. 解决办法: 使用jsonconf ...
- PHP运算符
运算符 PHP运算符可以根据操作数的个数分为一元运算符.二元运算符.三元运算符.一元运算符例如!(取反运算符)或++(加一运算符),PHP支持的大多数运算符都是这种二元运算符,例如+.-.*./等算数 ...
- MongoDb gridfs-ngnix文件存储方案
在各类系统应用服务端开发中,我们经常会遇到文件存储的问题. 常见的磁盘文件系统,DBMS传统文件流存储.今天我们看一下基于NoSQL数据库MongoDb的存储方案.笔者环境 以CentOS ...
- JMeter专题系列(三)元件的作用域与执行顺序
1.元件的作用域 JMeter中共有8类可被执行的元件(测试计划与线程组不属于元件),这些元件中,取样器是典型的不与其它元件发生交互作用的元件,逻辑控制器只对其子节点的取样器有效,而其它元件(conf ...
- 功能强大的滚动播放插件JQ-Slide
查看效果:http://keleyi.com/keleyi/phtml/jqplug/4.htmJQ-Slide插件功能强大,滚动方式自由多样全部滚动方式 方式一 方式二 方式三 方式四 方式五 方式 ...
- artTemplate模板引擎学习实战
在我的一篇关于智能搜索框异步加载数据的文章中,有博友给我留言,认为我手写字符串拼接效率过低,容易出错.在经过一段时间的摸索和学习之后,发现现在拼接字符串的方法都不在是自己去书写了,而是使用Javasc ...
- window对象的属性及事件。
不同的运行环境有不同的“顶层对象”,而在浏览器的环境中,顶层对象就是window对象.window就是指当前的浏览器窗口. 例:var a = 1: window.a; //1 1.window对象的 ...
- Atitit.去除水印的方案
Atitit.去除水印的方案 1.1. 查找水印的位置 Kegwa imgd posit zo ok le .. Auto find d zo troub ...manu easy 1.2. 还原去除 ...
- OC 协议
OC 协议 概念:定义了一个接口,其他类负责来实现这些接口.如果你的类实现了一个协议的方法时,则说该类遵循此协议. 非正式协议:非正式协议虽名为协议,但实际上是挂于NSObject上的未实现分类(Un ...
- ThinkPHP3快速入门教程二:数据CURD
CURD(创建[Create].更新[Updata].读取[Read].删除[Delete]),定义了用于处理数据的基本原子操作. CURD在具体的应用中并非一定使用create.updata.rea ...