liurunyu
2025-03-21 fb50c6c8111fffd16091ce25d5d389ea3fcc560f
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
package com.dy.common.util;
 
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
 
import java.util.Calendar;
 
@Slf4j
@Component
public class IDLongGenerator {
 
    private static final Object synObj = new Object() ;
 
    private static final int yearLength = 4 ;//4:年度取四位, 3:年度取三位, 2:年度取两位, 1:年度取一位, 0:年度取0位
 
    private static int add = 0 ;
    private static final int chengShu = 1000 ;//1000:三位自增量,即一秒钟可产生10000个ID
    private static final int maxAdd = 999 ;
    private static long last;
    //后缀
    //在分布式系统中,例如多个数据中间件dataMw,多个系统都会向数据库中插入数据,用的都是此ID生成器,
    //此ID生成器在各个子系统中难免为同一类数据生成相同的ID,造成数据库插入因主键相同而报错,
    //所以设计此后缀,每个子系统后缀不同
    private static int suffix = 0 ;
    private static final int noSuffix = 0 ;
 
    static {
        last = current() ;
    }
 
    /**
     *  2023 10 28 09 14 40 00000
     * 长度19的ID,年度取两位,长度18的ID,年度取四位,17位数字超出了javascript的表数范围,javascript会表数不正确
     */
    public Long generate(){
        synchronized (synObj){
            //Long id = doGenerate() ;
            //log.info("产生ID = " + id);
            //return id ;
            return doGenerate() ;
        }
    }
    /**
     * 设置后缀,不同子系统设置不同的后缀
     * @param suffix ID后缀,0到99
     */
    public static void setSuffix(int suffix) throws Exception{
        if(suffix < 0 || suffix > 99){
            throw new Exception("后缀只能是0到99的数字") ;
        }
        IDLongGenerator.suffix = suffix ;
    }
 
 
    /**
     * 得到今日开始的id(如: 230630 00000000000)
     * @return ID
     */
    public static Long generateTodayStartId(){
        return (currentTodayStart() * chengShu) * 100 + noSuffix;
    }
    
    /**
     * 得到今日截止的id(如: 230630 24000000000)
     * @return ID
     */
    public static Long generateTodayEndId(){
        return (currentTodayEnd() * chengShu) * 100 + noSuffix;
    }
    
    
    /**
     * 得到某日开始的id(如: 230630 00000000000)
     * @return ID
     */
    public static Long generateBeforeXDayStartId(int xday){
        return (beforeXDayStart(xday) * chengShu) * 100 + noSuffix;
    }
    
    /**
     * 得到某日截止的id(如: 230630 24000000000)
     * @return ID
     */
    public static Long generateBeforeXDayEndId(int xday){
        return (beforeXDayEnd(xday) * chengShu) * 100 + noSuffix;
    }
  
    
    /**
     * 得到某日开始的id(如: 230630 00000000000)
     * @return ID
     */
    public static Long generateOneDayStartId(int year, int month, int day){
        return (currentOneDayStart(year, month, day) * chengShu) * 100 + suffix;
    }
    
    /**
     * 得到某日截止的id(如: 230630 24000000000)
     * @return ID
     */
    public static Long generateOneDayEndId(int year, int month, int day){
        return (currentOneDayEnd(year, month, day) * chengShu) * 100 + suffix;
    }
 
    
 
    /**
     * 执行生成
     * @return ID 20231218 104504 06900
     */
    private Long doGenerate(){
        long id ;
        long now = current() ;
        if(now != last){
            //上次生成ID 与本次生成ID 不在同一秒内
            last = now ;
            add = 0 ;
            id = last * chengShu + add++;
        }else{
            //上次生成ID 与本次生成ID 在同一秒内
            if(add >= maxAdd){
                //附加量已经用尽
                waitNextSecond(last) ;//等到下一秒
                id = last * chengShu + add++ ;//返回上一秒生成的ID
                add = 0 ;//附加量归零,为下一秒准备
            }else{
                //附加量未用尽
                id = last * chengShu + add++ ;
            }
        }
        return (id * 100) + suffix ;
    }
    /**
     * 等待下一秒到来
     * @param last 上次时间(精确到秒)
     */
    private void waitNextSecond(Long last){
        try {
            Thread.sleep(10);
        } catch (InterruptedException ignored) {
        }finally{
            long now = current() ;
            if(now == last){
                waitNextSecond(last) ;
            }
        }
    }
 
   
    
    /**
     * 格式为 y*yMMddHHmmss
     * @return ID
     */
    private static long current(){
        Calendar cal = Calendar.getInstance();
        return (dealYear(cal.get(Calendar.YEAR))) * 10000000000L
        + (cal.get(Calendar.MONTH) + 1) * 100000000L
        + cal.get(Calendar.DAY_OF_MONTH) * 1000000L
        + cal.get(Calendar.HOUR_OF_DAY) * 10000L
        + cal.get(Calendar.MINUTE) * 100L
        + cal.get(Calendar.SECOND)  ;
    }
   
    
    /**
     * 格式为 
     * @return ID
     */
    private static long currentTodayStart(){
        Calendar cal = Calendar.getInstance();
        return (dealYear(cal.get(Calendar.YEAR))) * 10000000000L
        + (cal.get(Calendar.MONTH) + 1) * 100000000L 
        + cal.get(Calendar.DAY_OF_MONTH) * 1000000L ;
    }
    
    /**
     * 格式为 
     * @return ID
     */
    private static long currentTodayEnd(){
        Calendar cal = Calendar.getInstance();
        return (dealYear(cal.get(Calendar.YEAR))) * 10000000000L
        + (cal.get(Calendar.MONTH) + 1) * 100000000L 
        + cal.get(Calendar.DAY_OF_MONTH) * 1000000L 
        + 24 * 10000L ;
    }
    
    
    /**
     * 格式为 
     * @return ID
     */
    private static long currentOneDayStart(int year, int month, int day){
        return (dealYear(year)) * 10000000000L
        + month * 100000000L 
        + day * 1000000L ;
    }
    
    /**
     * 格式为 
     * @return ID
     */
    private static long currentOneDayEnd(int year, int month, int day){
        return (dealYear(year)) * 10000000000L
        + month * 100000000L 
        + day * 1000000L 
        + 24 * 10000L ;
    }
    
    /**
     * 格式为 
     * @return ID
     */
    private static long beforeXDayStart(int xday){
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, xday<=0?xday:-xday);
        return (dealYear(cal.get(Calendar.YEAR))) * 10000000000L
        + (cal.get(Calendar.MONTH) + 1) * 100000000L 
        + cal.get(Calendar.DAY_OF_MONTH) * 1000000L ;
    }
    
    /**
     * 格式为 
     * @return ID
     */
    private static long beforeXDayEnd(int xday){
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, xday<=0?xday:-xday);
        return (dealYear(cal.get(Calendar.YEAR))) * 10000000000L
        + (cal.get(Calendar.MONTH) + 1) * 100000000L 
        + cal.get(Calendar.DAY_OF_MONTH) * 1000000L 
        + 24 * 10000L ;
    }
 
    /**
     * 处理年度
     * @param year 年度
     * @return 处理后的年度
     */
    private static int dealYear(int year){
        if(yearLength == 0){
            return 0 ;
        }else if(yearLength == 1){
            return year % 10 ;
        }else if(yearLength == 2){
            return year % 100 ;
        }else if(yearLength == 3){
            return year % 1000 ;
        }else if(yearLength == 4){
            return year ;
        }else{
            return year ;
        }
    }
 
//    public static void main(String[] args){
//        Calendar cal = Calendar.getInstance();
//        System.out.println(cal.get(Calendar.MONTH) + 1) ;
//
//        IDLongGenerator o = new IDLongGenerator() ;
//        int total = 1 ;
//        for(int i = 0 ; i < total ; i++){
//            System.out.println(o.generate()) ;
//        }
//        long start = System.currentTimeMillis() ;
//        long end = System.currentTimeMillis() ;
//        System.out.println("产生" + total + "ID用时" + (end - start) + "毫秒");
//
//        Long todayStartId = IDLongGenerator.generateTodayStartId() ;
//        System.out.println("today start id:\n" + todayStartId);
//        Long todayEndId = IDLongGenerator.generateTodayEndId() ;
//        System.out.println("today end id:\n" + todayEndId);
//
//
//        Long beforeXDayStartId = IDLongGenerator.generateBeforeXDayStartId(3) ;
//        System.out.println("before3Day start id:\n" + beforeXDayStartId);
//        Long beforeXDayEndId = IDLongGenerator.generateBeforeXDayEndId(3) ;
//        System.out.println("before3Day end id:\n" + beforeXDayEndId);
//
//
//        Long oneDayStartId = IDLongGenerator.generateOneDayStartId(2023, 7, 9) ;
//        System.out.println("OneDay(2023-07-09) start id:\n" + oneDayStartId);
//        Long oneDayEndId = IDLongGenerator.generateOneDayEndId(2023, 7, 11) ;
//        System.out.println("OneDay(2023-07-11) end id:\n" + oneDayEndId);
//    }
    
}