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 ...
随机推荐
- Atitit.ide eclipse编译速度慢的解决
Atitit.ide eclipse编译速度慢的解决 以为是jar的体积与数量,貌似无关.. Err java的数量,貌似无关 Java的数量,关系不大... 最终原因:show>>pro ...
- Java编程里类的继承
今天,我们将要讨论的内容是Java里面类的继承的相关概念. 说到继承,我相信大家都不陌生.生活中,子承父业,子女继承父母的财产,这就是继承.实际上,Java里的继承也是如此.对于一个类来说,它的数据成 ...
- Java基础学习 -- I/O系统、流
Java类库里有四个表示流的抽象父类:InputStream.OutputStream.Reader.Writer. 其中 InputStream 和 OutputStream 是对字节进行操作的输入 ...
- CSS3与页面布局学习笔记(四)——页面布局大全(负边距、双飞翼、多栏、弹性、流式、瀑布流、响应式布局)
一.负边距与浮动布局 1.1.负边距 所谓的负边距就是margin取负值的情况,如margin:-100px,margin:-100%.当一个元素与另一个元素margin取负值时将拉近距离.常见的功能 ...
- 游标的使用——mysql
CREATE DEFINER=`root`@`%` PROCEDURE `split_category_all`()BEGIN declare categ varchar(10); ##套餐列 dec ...
- checkbox & radio 的对齐问题
不仅不同浏览器不同,不同的字体,不同的文字大小也会表现不一样. 重置 form checkbox & radio 因为不同浏览器解析不一样,有些是默认margin,有些是默认padding,还 ...
- How To Search and Restore files from Site Collection Recycle Bin
$sitecoll = Get-SPSite "http://wheresmydoc.findit.com" $sitecoll.RecycleBin | ?{$_.Title - ...
- Android的四大组件之Activity
Android的四大组件之Activity Activity:是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,B ...
- tableview左滑按钮 tableviewcell自定义左滑按钮
当我们在使用tableview时,往往需要在cell左滑时显示一个或是多个按钮,但系统默认的只可显示一个,如常见的删除按钮,那么当我们的需求要求要有多个按钮时又该怎么办呢,我们往下看. 首先,现看看系 ...
- J2ObjC 1.0 发布,将 Java 转换为 Objective-C
J2ObjC 是一个Google开发的开源工具,用于将Java代码转换为Objective-C代码.其目的是为了能在iOS平台上重用Android平台.web服务器端的Java代码.服务器端代码的转换 ...